I'm using this XPath query to select elements that do not have input descendants in an Xhtml document:
//*[not(descendant-or-self::input | descendant-or-self::textarea | descendant-or-self::select | ancestor::select)]
With the following example XHtml document:
<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>
...And this PHP code:
// 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 ' ';
}
I get this: head title div#three div#four div#seven div#eight
But I want this instead: head div#three div#seven
I will be taking the results of the XPath query and removing the elements from DOMDocument. title div#four div#eight
are children of head div#three div#seven
, which are already in the result.
Keeping in mind this query will be used on any XHtml document, how would I change my XPath 1.0 query to get the desired results?
Just repeat the condition for the parent:
[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)]