newtover
newtover

Reputation: 32094

What does xpath expression '//ancestor::*[@id][1]' actually mean

Answering a question, I noticed strange libxml behavior on the following expression:

//ancestor::*[@id][1]

for a given context node. I am trying to understand what the expression actually means.

Here is a snippet in PHP and result of its invocation:

$html = <<<HTML
<div id="div1">
    <div id="div2">
        <p id="p1">Content</p>
    </div>
    <div id="div3">
        <p id="p2">Content</p>
    </div>
</div>
HTML;

$doc = new DOMDocument();
$doc->loadHTML($html);
$xpath = new DOMXpath($doc);

$contextNode = $doc->getElementById('p1');
$list = $xpath->query('//ancestor::*[@id][1]', $contextNode);

printf("NodeList length: %d\n", $list -> length);
foreach ($list as $node) {
    printf ("item/@id -> %s\n", $node -> getAttribute('id'));
}

Result:

NodeList length: 5
item/@id -> div1
item/@id -> div2
item/@id -> p1
item/@id -> div3
item/@id -> p2

Upvotes: 0

Views: 796

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167516

//ancestor::*[@id][1] is a short form for /descendant-or-self::node()/ancestor::*[@id][1] so the context node is only relevant for determining its root or document node /, then in the first step descendand-or-self::node() a node-set is formed of the document node and all its descendant nodes of all kinds (element nodes, text nodes, comment nodes, processing instruction nodes), then the next step for each of those nodes determines ancestor::*[@id][1], that is of all ancestor elements having an id attribute the first one.

Upvotes: 4

Related Questions