簡體   English   中英

相同的XPath-不同的結果

[英]The same XPaths - different results

$str = '
<body>
<table><tr><td><b class="1">1</b></td></tr></table>
<table><tr><td><b class="2">1</b></td></tr></table>
<p>some text</p>
</body>';

$dom = new DOMDocument();
$dom->loadHTML($str);
$xpath = new DOMXpath($dom);

foreach($xpath->query('//table[//b[contains(@class, "2")]]') as $i) 
   print_r($i);

echo "------------------------------------------\n";

foreach($xpath->query('//table//b[contains(@class, "2")]/ancestor::table') as $i) 
   print_r($i);

第一個XPath選擇兩個表,而第二個僅獲取目標(第二個)表。 為什么?

評估

接受的答案可以糾正錯誤,但不能真正解釋原始路徑表達式為什么出錯。

您的第一個表達式如下:

//table[//b[contains(@class, "2")]]

它有兩個謂詞 ,一個嵌套在另一個中:

//table[//b[contains(@class, "2")]]
           ^---------------------^       inner predicate
       ^--------------------------^      outer predicate

將謂詞視為應用於謂詞左側上下文的過濾器。 在極端情況下,此類謂詞不會丟棄任何中間結果節點,也不會丟棄所有中間結果節點。

每個中間結果節點只有在其右邊的謂詞評估為true才會保留。 對於內部謂詞:

//b[contains(@class, "2")]

//b產生一組中間的b元素節點(整個文檔中的所有b元素節點),然后由謂詞[contains(@class, "2")]過濾。 給定您輸入的XML文檔,謂詞內部的表達式僅對b元素之一返回true

但是//b[contains(@class, "2")]依次充當外部謂詞的內容:

//table[outer predicate]

現在, //table選擇整個文檔中所有table元素節點作為中間結果,並對每個謂詞檢查謂詞內部的表達式。

重要的是,外部謂詞//b[contains(@class, "2")]對於兩個 table元素將返回true 這是因為對於他們兩個來說,在整個文檔中某處確實存在一個b元素,其class屬性包含2

您真正想做的是:從每個table元素的角度評估外部謂詞表達式-接受的答案顯示了如何執行此操作。 即,在謂詞中使用.//代替//

XPath謂詞[//b...]有一個錯誤。 它應該是[.//b...]

說明: [...]是謂詞,它們僅充當過濾器。 a[b] ,選擇所有滿足謂詞[b] a節點。 如果ab是元素,它會,從當前上下文節點,選擇所有a包含一個元素b元件作為子元素。

  • //bAbbreviatedAbsoluteLocationPath並選擇整個文檔中的所有b元素節點。 兩個表都在帶有b元素的文檔中,因此謂詞[//b]對於您的文檔始終為true,無論您在哪里應用它。
  • .//bAbbreviatedRelativeLocationPath並選擇作為后代的所有b元素節點(子代及其子代,遞歸)。 謂詞[.//b]僅適用於具有后代元素b table元素。

如果步驟路徑表達式選擇的節點集不為空,則像//b.//b這樣的步驟路徑表達式在用作[//b][.//b]類的謂詞時為true

由於//b而不是.//b ,因此應用的謂詞沒有任何改變: //b[contains(@class, "2")]選擇整個文檔中所有包含“ 2”的元素在其class屬性中。 您基本上是在檢查文檔,而不是對所需table元素下方的樹進行檢查,並且兩個table元素都滿足該文檔檢查的要求,因為這兩個檢查都在文檔中,該文檔的class屬性中包含一個b元素帶有“ 2”的元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM