2010-04-11 82 views
43

我試圖對由xpath查找返回的節點執行xpath查找,但它似乎沒有像我期望的那樣工作。在文檔的子節點上執行的XPath似乎被執行h文檔的根節點(在本例中爲庫存標籤),而不是所提供節點的根節點。在子節點上運行XPath

我在這裏錯過了什麼嗎?我是XPath新手。

此外,請不要回答「只要做//書[作者='尼爾斯蒂芬森'/標題」。我有一個合法的用例,這是一個簡單的例子。

代碼片斷

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> 
+1

其他人已經爲您的問題提供了很好的答案。請注意,'// book'和其他以'//開頭的表達式可能會影響性能,因爲必須搜索整個DOM樹。 '/ inventory/book'更有效率。同樣,如果一個XPath表達式被多次使用,你應該用'XPath.compile()'編譯一次,然後在結果上運行'XPathExpression.evaluate()',而不是重複調用'XPath評估()'。 – markusk 2010-04-11 20:38:35

+1

在這裏回答:http://stackoverflow.com/questions/8358994/xpath-search-on-subtree – Benj 2013-05-09 14:45:38

+0

它不僅在Java中這樣工作。 .NET做同樣的事情。 – ajeh 2016-09-28 17:01:48

回答

43

/foo將根據根節點進行選擇,忽略您正在評估xpath的上下文。 foo(沒有斜線)是你想要的;該選擇基於當前節點。

https://www.w3schools.com/xml/xpath_syntax.asp給出了一些信息。

+4

感謝您的澄清。我會遠離w3schools,這些w3schools的內容很差或者大部分xml主題。 – MonoThreaded 2013-02-08 13:06:28

+2

w3schools是有限的,缺乏重點,當然,但它非常方便。互聯網嚴重缺乏對技術的基本解釋。雖然你和我可能不需要這樣的事情,但是對於那些外行來說,w3schools是一個很好的地方,可以讓他們在去更重要的地方之前瞭解他們正在處理的事情。 – meustrus 2014-07-28 19:25:37

+0

如果我想使用書籍節點「// book [@ year ='2000']/title」怎麼辦? – 2017-03-01 11:29:59

7

只取斜線把你的子查詢,你應該罰款。所以你通過"//book"得到你的書,然後從那裏它只是"title""inventory"等得到孩子位。

3

Java實現中真正奇怪的是,從文檔中提取的節點仍然引用父文檔(請參閱Node.getOwnerDocument()),xpath使用它來查找根。

其他人提到一種方法來修改xpath實際上不是通過刪除斜槓從根開始。

我有一個類似的問題,但我希望xpath處理根文檔和子節點(使用xpath如/title)。解決方法是到克隆節點:Node.cloneNode(true)。請注意0​​參數使Node關閉其父文檔。

......最後,它損害了性能太多,並有單獨的xpath來處理節點和文檔是首選。

+0

如果性能不是問題,這是一個很好的解決方案(或解決方法...)! – Ice09 2013-02-26 09:10:32

+0

我不認爲這是特定於Java的。我在Java,PHP和JavaScript中使用了DOM,並且在所有三種語言中,接口幾乎完全相同,包括節點繼續記住其父文檔直到克隆到新的上下文中的方式。 – meustrus 2014-07-28 19:28:29

19

in Xpath,「。」 (點)代表當前文件。 因此,在「。」之後寫入XPATH字符串。 (點)。

例如:

"./title" 

".//title" 

無論你想要什麼....

去掉斜線只能如果該節點的孩子。 如果您想使用//(當前文檔中的任何位置)功能,該怎麼辦?

因此,使用點(。)

非常感謝上面的答案太:)。