当需要处理具有不同名称的字段时,如何通过一个XPATH语句更新多个节点?
答案 0 :(得分:2)
我不确定你在发布这个问题时的目标是什么,但我看到你自己的答案有几个问题。
if
语句的正文是重复的代码,违反了DRY主体。鉴于您需要从所选节点向上导航,这可能会导致错误 - 或者复制并粘贴代码,如果您更改了指定表达式的方式,则必须在多个位置进行更改。在我看来,提取一个选择节点并一次对单个表达式执行更改的方法要好得多。从您的代码开始,让我的IDE修复一些语法错误,我最终得到了这个(但是,我还没有编写测试用例):
public static void main(String[] args) throws Exception
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("path/to/file.xml"));
changeNodeText(doc, "/PersonList/Person/Age", "42");
changeNodeText(doc, "/PersonList/Person/Name", "Batman");
}
public static void changeNodeText(Node context, String xpath, String value)
throws XPathExpressionException
{
XPathFactory xFactory = XPathFactory.newInstance();
XPath xPath = xFactory.newXPath();
XPathExpression expression = xPath.compile(xpath);
NodeList nodes = (NodeList)expression.evaluate(context, XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++)
{
Node node = nodes.item(i);
node.setTextContent(value);
}
}
一些关键功能(除了我上面提到的XPath特定注释):
setTextContent()
方法,IMO的规范比setNodeValue()
更好(除非您传递文本节点,否则会失败)。答案 1 :(得分:0)
给出这样的架构:
<?xml version="1.0" encoding="UTF-8"?>
<PersonList>
<Person>
<Name>Adam West </Name>
<Age> 72 </Age>
</Person>
</PersonList>
以下代码会将名称字段更新为Batman
,将年龄字段更新为42
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public static void main(String[] args) throws Exception
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new File("path/to/file.xml"));
XPathFactory xFactory = XPathFactory.newInstance();
XPath xPath = xFactory.newXPath();
XPathExpression expression = xPath.compile("PersonList/Person/Age/text() | PersonList/Person/Name/text()");
NodeList nodes = (NodeList) expression.evaluate(doc,XPathConstants.NODESET);
for(int i = 0; i <nodes.getLength() i++)
{
Node node = nodes.item(i);
if(node.getPArentNode().getNodeName().equals("Name")
{
node.setNodeValue("Batman");
} else
{
node.setNodeValue("42"); // you may need more else/if blocks / switch
}
}
}