2012-10-13 37 views
25

鑑於類似這樣的標記:有沒有更好的方法獲取XPath查詢結果的父節點?

<div class="foo"> 
    <div><span class="a1"></span><a href="...">...</a></div> 
    <div><span class="a2"></span><a href="...">...</a></div> 
    <div><span class="a1"></span>some text</div> 
    <div><span class="a3"></span>some text</div> 
</div> 

現在我感興趣的是得到這些<a>some text只有當相鄰spana1類的。因此,在整個代碼結束時,我的結果是<a>從第一個divsome text。這很容易,如果<a>some text裏面spandiv將具有class屬性,但沒有運氣。

我現在正在做的是spana1類這樣的查詢:

//div[contains(@class,'foo')]/div/span[contains(@class,'a1')] 

,然後獲取其父母,做一套query()與作爲上下文節點是父節點。這看起來遠沒有效率,所以有沒有更好的方法來做到這一點?


答案

按@MarcB answer,正確的查詢是:

//div[contains(@class,'foo')]/div/span[contains(@class,'a1')]/.. 

<A>它可能是更好的使用:

//div[contains(@class,'foo')]/div/span[contains(@class,'a1')]/../a 

獲得<A>代替它的容器。

回答

54

約XPath查詢的好處是,你基本上可以把他們當作一個文件系統路徑,因此僅僅擁有

//div[contains(@class,'foo')]/div/span[contains(@class,'a1')]/.. 
                   ^^ 

會發現,是包含.foo節點下的所有指定.A1節點,然後移動向a1節點的父母上一層。

+4

+1的文件系統路徑的參考,這就是我怎麼樣了總是想到它,但我從來沒有聽說過這樣解釋 –

+1

我剛纔檢查手冊之前問這個問題,但似乎我設法錯過了「..」,因爲它顯然存在。但FS參考立即清楚。謝謝。 –

+1

是的。當我第一次跳入xpath時,我像這樣徘徊了一段時間,但是使查詢<->路徑關聯對我來說是非常適合的。 –

16

表達比使用逆轉錄軸更好

//div[contains(@class,'foo')]/div[span[contains(@class,'a1')]] 

這將選擇任何div這是一個divclass屬性的子包含字符串「foo」,並且(所選div)有一個span孩子,其class屬性包含字符串「a1」。

XSLT - 基於驗證

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:copy-of select= 
    "//div[contains(@class,'foo')] 
      /div[span[contains(@class,'a1')]]"/> 
</xsl:template> 
</xsl:stylesheet> 

當該變換被應用所提供的XML文檔:

<div class="foo"> 
    <div><span class="a1"></span><a href="...">...</a></div> 
    <div><span class="a2"></span><a href="...">...</a></div> 
    <div><span class="a1"></span>some text</div> 
    <div><span class="a3"></span>some text</div> 
</div> 

XPath表達式求值和所選擇的元素複製到輸出:

<div> 
    <span class="a1"/> 
    <a href="...">...</a> 
</div> 
<div> 
    <span class="a1"/>some text</div> 

二,通過它的類的一個訪問HTML元素備註:如果已知該元素只能有一個類

,那麼就沒有必要在所有使用

不要使用

//div[contains(@class, 'foo')] 

使用

//div[@class = 'foo'] 

或者,如果有可能是前/後間隔,使用方法:

//div[normalize-space(@class) = 'foo'] 

一個關鍵問題與

//div[contains(@class, 'foo')] 

是,這個選擇與任何同類div如 「myfoo」 ,「foo2」或「myfoo3」。

如果該元素可以有多個類,並避免上述問題,正確的XPath表達式是

//div[contains(concat(' ', @class, ' '), ' foo ')] 
+2

不要忘記html允許多個類。 '@ class ='foo''將跳過'class =「foo bar baz」'。因此,@contains是完全有效的,只要你指出,你注意到誤報 –

+3

@MarcB,看來你還沒有閱讀或理解這個答案 - 它將長時間處理一個元素有不止一節課。而且,這個答案爲這種情況提供了一個正確的解決方案 - 不像不正確和簡單的'包含(@calss,someString)' –

相關問題