当需要处理不同名称的字段时,如何通过一个 XPATH 语句更新多个节点?
最佳答案
我不确定您发布此问题的目的是什么,但我发现您自己的答案存在几个问题。
- XPath 是一个将谓词应用于 DOM 树的工具。使用 XPath 选择比您需要的更大的节点集,然后将您自己的谓词应用于它返回的节点列表是没有意义的。
- 您的 XPath 表达式包含多个正交项。这评估效率较低,并且当您添加其他术语时很快就会变得难以管理。
- 您使用的表达式(检索文本节点然后导航到父元素)没有多大意义。我想您只想选择已经有文本的节点,但如果您正在进行全局搜索并替换,我不确定这是一个合理的假设。如果我要继承您的代码,我当然希望看到演示这两种行为的测试,以表明您想要该行为。
- 长长的 if/else 语句链非常难以理解。它们也很难测试,因为您必须制作一个测试套件来执行代码中所有可能的路径。
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()
有更好的规范(除非您传递文本节点,否则它将失败)。 - 如果您必须添加命名空间映射,您可以在一个地方完成。如果您决定只想更改已经具有文本节点的元素,则同上。
关于java - 如何通过 XPATH 更新 Java 中需要不同值的多个节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17282954/