Java 在子节点上运行XPath

Java 在子节点上运行XPath,java,xpath,Java,Xpath,我正在尝试对xpath查找返回的节点执行xpath查找,但它似乎没有像我预期的那样工作。在文档的子节点上执行的xpath似乎是针对文档的根节点(在示例中是inventory标记)而不是所提供节点的根节点执行的 我是不是遗漏了什么?我不熟悉XPath 另外,请不要回答“just do//book[author='Neal Stephenson'/title”。我有一个合法的用例,这是一个简化的示例 代码片段 DocumentBuilderFactory domFactory = DocumentB

我正在尝试对xpath查找返回的节点执行xpath查找,但它似乎没有像我预期的那样工作。在文档的子节点上执行的xpath似乎是针对文档的根节点(在示例中是inventory标记)而不是所提供节点的根节点执行的

我是不是遗漏了什么?我不熟悉XPath

另外,请不要回答“just do//book[author='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>

雪崩
尼尔·斯蒂芬森
光谱
0553380958
14.95
燃烧塔
拉里·尼文
杰里·波内尔
口袋
0743416910
5.99
生肖
尼尔·斯蒂芬森
光谱
0553573862
7.50

只需将子查询的前导斜杠去掉,您就可以了。因此,您可以通过
“//book”
获取书籍,然后从那里获得
“title”
“inventory”
等以获取子位。

/foo
将基于根节点进行选择,忽略您计算xpath所依据的上下文。
foo
(不带斜杠)是您想要的;它基于当前节点进行选择


提供了更多信息。

Java实现中真正奇怪的是,从文档中提取的节点仍然引用父文档(请参见
Node.getOwnerDocument()
),xpath使用它来查找根

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

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

…最后,它对性能影响太大,最好使用单独的Xpath来处理节点和文档。

在Xpath中,“.”(点)表示当前文档。 因此,在“.”(点)后编写XPATH字符串

例:

你想要什么都行

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

所以,使用点()


非常感谢上面的回答:)。

其他人对您的问题提供了很好的答案。请注意,
//book
和其他以
//
开头的表达式可能会影响性能,因为必须搜索整个DOM树。
/inventory/book
效率更高。同样,如果XPath表达式要多次使用,您可能应该使用XPath.compile()编译一次,然后对结果运行
XPathExpression.evaluate()
,而不是重复调用
XPath.evaluate()
。这里回答:它不仅在Java中是这样工作的。NET也做同样的事情。感谢您的澄清。我将远离内容非常差或xml主题最多的w3schools。w3schools是有限的,缺乏重点,当然,但它非常容易访问。互联网严重缺乏对技术的良好基本解释。While you和我可能不需要这样的东西,w3schools是一个很好的地方,让不熟悉的人在去更实际的地方之前了解他们正在处理的事情。如果我想用“//book[@year='2000']/title”使用book node怎么办?如果性能不是问题,这是一个很好的解决方案(或解决方法…)!我不认为这是Java特有的。我在Java、PHP和JavaScript中使用过DOM,在所有三种语言中,接口几乎相同,包括节点在克隆到新上下文之前继续记住其父文档的方式。
"./title"
".//title"