2012-02-14 58 views
1

我使用這個XPath查詢選擇沒有輸入後代XHTML文檔中的元素:如何僅選擇此XPath查詢中的「頂級節點」?

//*[not(descendant-or-self::input | descendant-or-self::textarea | descendant-or-self::select | ancestor::select)] 

用下面的例子XHTML文檔:

<html> 
    <head> 
     <title>Title</title> 
    </head> 
    <body> 
     <div id="one"> 
      <input type="text" /> 
     </div> 
     <div id="two"> 
      <textarea></textarea> 
     </div> 
     <div id="three"> 
      <div id="four"> 
       Text 
      </div> 
     </div> 
     <div id="five"> 
      <select> 
       <option>One</option> 
       <option>Two</option> 
      </select> 
     </div> 
     <div id="six"> 
      <input type="text" /> 
     </div> 
     <div id="seven"> 
      <div id="eight"></div> 
     </div> 
    </body> 
</html> 

...這PHP代碼:

// Populate $html and $query with above 

$dom = new DOMDocument('1.0', 'UTF-8'); 
$dom->loadXML($html); 

$xpath = new DOMXPath($dom); 
$nodes = $xpath->query($query); 

foreach($nodes as $node) 
{ 
    echo $node->tagName; 

    if($node->hasAttribute('id')) 
     echo '#' . $node->getAttribute('id'); 

    echo ' '; 
} 

我得到這個:head title div#three div#four div#seven div#eight

但我想要這個:head div#three div#seven

我將採取XPath查詢的結果並從DOMDocument中刪除元素。 title div#four div#eighthead div#three div#seven的子項,它們已經在結果中。

記住這個查詢將用於任何XHtml文檔,我將如何更改我的XPath 1.0查詢以獲得所需的結果?

回答

1

只是重複的條件父:

[not(descendant-or-self::input | descendant-or-self::textarea | descendant-or-self::select | ancestor-or-self::select) 
and 
(../descendant-or-self::input | ../descendant-or-self::textarea | ../descendant-or-self::select | ../ancestor-or-self::select)] 
+0

這個工程!似乎只要重複的條件是'和(../descendant::put | ../descendant::textarea | ../ descendant :: select)'就足夠了。第一個條件中的「祖先或自我選擇」部分確保了「select」的內部是獨立的。如果我理解正確,'../'部分選擇「根父」,這正是我想要的,謝謝:)。如果沒有字段元素,我還添加了一個回退選擇根節點'html'。 – Luke 2012-02-14 17:48:10

+0

當'html'元素出現'xmlns'屬性時,我發現查詢不起作用。因爲什麼原因,你不能簡單地執行'$ xpath-> registerNamespace(NULL,'http://www.w3.org/1999/xhtml')'...因此,你必須將'NULL'改爲' 'html',當xmlns存在時,執行'$ query = str_replace('::',':: input:',$ query)'。你可以使用'$ xmlns = $ document-> lookupNamespaceURI(NULL)'來查看它是否存在。希望有更好的方法。如果有,請告訴我! – Luke 2012-02-14 19:11:42

0

在這種情況下,它似乎是足夠的擴展您當前的XPath額外說,不應該有一個divancestorhead

//*[not(descendant-or-self::input 
     | descendant-or-self::textarea 
     | descendant-or-self::select 
     | ancestor::select 
     | ancestor::div 
     | ancestor::head)] 

在示例XML,這僅返回headdiv s threeseven,如果需要的話。

+0

不幸的是這不會爲每個XHTML/HTML5文件的工作。這太具體了。我只能對錶單字段進行具體說明。有ton塊/內聯元素可以包含一個表單域,這將不得不在這裏列出。缺少其中一個可能會導致錯誤(試圖刪除父母已被刪除的標籤)。 – Luke 2012-02-14 15:37:12