在子节点上运行XPath

Jee*_*Kim 49 java xpath

我正在尝试对xpath查找返回的节点执行xpath查找,但它似乎没有按预期工作.在文档的子节点上执行的XPaths似乎是针对文档的根节点执行的(在例如,库存标签.),而不是提供的节点的根.

我在这里错过了什么吗?我是XPath的新手.

另外,请不要回答"只做//书[作者='Neal Stephenson'/ title".我有一个合法的用例,这是一个简化的例子.

代码段

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("src/main/java/books.xml");

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();

Node book = (Node) xpath.evaluate("//book[author='Neal Stephenson']", doc, XPathConstants.NODE);
Node title = (Node) xpath.evaluate("/title", book, XPathConstants.NODE); // I get null here.
Node inventory = (Node) xpath.evaluate("/inventory", book, XPathConstants.NODE); // this returns a node.
Run Code Online (Sandbox Code Playgroud)

是book.xml

<inventory>
<book year="2000">
    <title>Snow Crash</title>
    <author>Neal Stephenson</author>
    <publisher>Spectra</publisher>
    <isbn>0553380958</isbn>
    <price>14.95</price>
</book>

<book year="2005">
    <title>Burning Tower</title>
    <author>Larry Niven</author>
    <author>Jerry Pournelle</author>
    <publisher>Pocket</publisher>
    <isbn>0743416910</isbn>
    <price>5.99</price>
</book>

<book year="1995">
    <title>Zodiac</title>
    <author>Neal Stephenson</author>
    <publisher>Spectra</publisher>
    <isbn>0553573862</isbn>
    <price>7.50</price>
</book>

<!-- more books... -->

</inventory>
Run Code Online (Sandbox Code Playgroud)

Pet*_*son 49

/foo将根据根节点进行选择,忽略您正在评估xpath的上下文.foo(没有斜线)是你想要的; 选择基于当前节点.

https://www.w3schools.com/xml/xpath_syntax.asp提供了更多信息.

  • 谢谢你的澄清.我会远离w3schools,内容非常差或大多数xml主题. (4认同)
  • w3schools是有限的,缺乏专注,当然,但它是非常容易接近的.互联网严重缺乏对技术的良好基本解释.虽然你和我可能不需要这样的事情,但是w3schools对于那些没有经验的人来说是一个很好的地方,可以在去更大的地方之前了解他们正在处理什么. (2认同)

小智 25

在Xpath中,"." (点)代表当前文档.所以,在"."之后写下你的XPATH字符串.(点).

例如:

"./title"
Run Code Online (Sandbox Code Playgroud)

要么

".//title"
Run Code Online (Sandbox Code Playgroud)

任何你想要的....

删除斜杠只有在它是节点的子节点时才有效.如果要使用//(当前文档中的任何位置)功能,该怎么办?

所以,使用点(.)

非常感谢上面的答案:).


Cor*_*ter 7

只需从你的子查询中删除主要的斜线就可以了.所以,您通过您的图书"//book",然后从那里它只是"title","inventory"等,以获得孩子的位.


mau*_*hiz 5

Java 实现中真正奇怪的是,从 Document 提取的 Node 仍然引用父 Document(请参阅 参考资料Node.getOwnerDocument()),而 xpath 使用它来查找根。

其他人提到了一种通过删除斜杠来修改 xpath 以使其实际上不是从根开始的方法。

我有一个类似的问题,但我希望 xpath 处理根文档和子节点(使用类似 的 xpath /title)。解决方案是克隆节点:Node.cloneNode(true)。请注意true使 Node 摆脱其父 Document的参数。

...最后,它对性能的影响太大了,最好使用单独的 xpath 来处理 Node 和 Document。