我希望使用xPath修改一个现有的XML文件。如果节点不存在,则应创建它(以及必要的父节点)。以下是示例:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<param0>true</param0>
<param1>1.0</param1>
</configuration>
以下是我想要插入/修改的两个XPath:
/configuration/param1/text() -> 4.0
/configuration/param2/text() -> "asdf"
/configuration/test/param3/text() -> true
XML文件应该长这个样子:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<param0>true</param0>
<param1>4.0</param1>
<param2>asdf</param2>
<test>
<param3>true</param3>
</test>
</configuration>
我尝试了这个:
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
try {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
Document doc = domFactory.newDocumentBuilder().parse(file.getAbsolutePath());
XPath xpath = XPathFactory.newInstance().newXPath();
String xPathStr = "/configuration/param1/text()";
Node node = ((NodeList) xpath.compile(xPathStr).evaluate(doc, XPathConstants.NODESET)).item(0);
System.out.printf("node value: %s\n", node.getNodeValue());
node.setNodeValue("4.0");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(doc), new StreamResult(file));
} catch (Exception e) {
e.printStackTrace();
}
运行此代码后,文件中的节点已更改。这正是我想要的。但如果我使用下面其中一条路径之一,node
将为 null(因此会抛出 NullPointerException
):
/configuration/param2/text()
/configuration/test/param3/text()
如何修改这段代码,以便创建节点(包括不存在的父节点)?
编辑:好吧,为了澄清:我有一组要保存到XML中的参数。在开发过程中,这个集合可能会改变(添加一些参数,移动一些参数,删除一些参数)。所以我想要一个函数将当前的参数集写入已经存在的文件中。它应该覆盖文件中已经存在的参数,添加新的参数并保留旧的参数。
读取也是同样的道理,我可以使用xPath或其他坐标从XML中获取值。如果它不存在,则返回空字符串。
对于实现方式,我没有任何限制,xPath、DOM、SAX、XSLT...一旦编写了功能,它应该很容易使用(就像BeniBela的解决方案)。
因此,如果我要设置以下参数:
/configuration/param1/text() -> 4.0
/configuration/param2/text() -> "asdf"
/configuration/test/param3/text() -> true
结果应该是起始XML加上这些参数。如果它们已经存在于该xPath,它们将被替换,否则它们将插入到该点。
javax.xml.xpath
) 和 XSLT (javax.xml.transform
) API,因此这些方法不会引入任何依赖关系。 - bdoughan