2012-02-14 92 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