我正在尝试对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.
是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>
答案 0 :(得分:48)
/foo
将根据根节点进行选择,忽略您正在评估xpath的上下文。 foo
(没有斜线)是你想要的;选择基于当前节点。
答案 1 :(得分:24)
在Xpath中,“。” (点)代表当前文档。 所以,在“。”之后写下你的XPATH字符串。 (点)。
前:
"./title"
或
".//title"
无论你想要什么......
删除斜杠只有在它是节点的子节点时才有效。 如果要使用//(当前文档中的任何位置)功能,该怎么办?
所以,使用点(。)
非常感谢上述答案:)。
答案 2 :(得分:7)
只需从你的子查询中删除前导即可,你应该没问题。因此,您可以通过"//book"
获取图书,然后从那里获取图书,只需"title"
,"inventory"
等来获取子位。
答案 3 :(得分:3)
Java实现中实际上奇怪的是,从Document中提取的节点仍然引用父文档(请参阅Node.getOwnerDocument()
),xpath使用它来查找根。
其他人已经提到了一种修改xpath的方法,通过删除斜杠来实际不从根开始。
我有一个类似的问题,但我希望xpath处理根文档和子节点(使用类似/title
的xpath)。解决方案是克隆节点:Node.cloneNode(true)
。请注意true
参数,该节点会使节点关闭其父文档。
...最后,它会对性能造成太大影响,并且首选单独的xpath来处理Node和Document。