2015-02-06 84 views
2

有人告訴我,以下是不一樣的:的XPath多謂詞等價

a[1][@attr="foo"] 
a[@attr="foo"][1] 

有人能解釋爲什麼會是這樣?

回答

2

思考XPath表達式作爲限定結果集 - 一組履行XPath表達式表示的所有要求的節點。 XPath表達式([]內部的部分)的謂詞或者對結果集沒有影響,或者它們遞增地縮小它

換句話說,在下面的表達式:

//xyz[@abc="yes"] 

[@abc="yes"]降低定義爲它的左側結果集,通過//xyz

請注意,正如Michael Kay所建議的,下面所說的全部內容僅適用於至少具有一個位置謂詞的XPath表達式。位置謂詞可以是數字:[1]或評估爲一個數字,或者包含position()last()

如果不存在位置謂詞,則XPath表達式中謂詞的順序不重要。


考慮以下簡單的輸入文件:

<root> 
    <a attr="other"/> 
    <a attr="foo"/> 
    <a attr="other"/> 
    <a attr="foo"/> 
</root> 

正如你所看到的,a[@attr = 'foo']root的第一個子元素。如果我們將

//a[1] 

這個文件,這當然會導致在

<a attr="other"/> 

現在,關鍵的是,如果我們添加另一個謂詞來表達,就像這樣:

//a[1][@attr="foo"] 

然後,[@attr="foo"]只能影響已由//a[1]定義的結果集。在這個結果集中,沒有a[@attr="foo"] - 最終結果是空的。

在另一方面,如果我們開始了與

//a[@attr="foo"] 

結果將是

<a attr="foo"/> 
----------------------- 
<a attr="foo"/> 

在這種情況下,如果我們添加第二個謂語:

//a[@attr="foo"][1] 

第二個謂詞[1]可以縮小//a[@attr="foo"]的結果集爲僅包含t他第一個那些節點。


如果你知道XSLT,你可能會發現一個XSLT(和XPath 2.0)證明這是很有幫助的:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> 

    <xsl:template match="/"> 
     <result1> 
      <xsl:copy-of select="//a[1][@attr='foo']"/> 
     </result1> 
     <result2> 
      <xsl:copy-of select="//a[@attr='foo'][1]"/> 
     </result2> 
    </xsl:template> 

</xsl:transform> 

而其結果將是

<result1/> 
<result2> 
    <a attr="foo"/> 
</result2> 

從技術上講,只有XPath 1.0將此結果稱爲節點集。在XPath 2.0中,所有集合都成爲節點的真實序列

+0

嗡嗡聲。感謝您通知我。我從來沒有想過你解釋的方式。 – 2015-02-06 10:13:41

+0

只要添加一個註釋,謂詞的順序只有在至少其中一個是「位置」時纔有意義。謂詞是位置的,如果它評估爲一個數字,或者它包含函數position()或last()上的調用。 – 2015-02-06 10:27:58

+0

@MichaelKay你是對的,這是一個重要的說明,我應該提到這一點!我馬上編輯我的答案。 – 2015-02-06 10:30:10