chrsmrrtt
chrsmrrtt

Reputation: 197

XPath - selecting descendants - difference between using // and */

Can someone help me understand the difference between the two following XPath queries:

A: //table[@id="xyz"]//tr[//a[contains(text(), "Alice")]]

B: //table[@id="xyz"]//tr[*/a[contains(text(), "Alice")]]

(A) appears to select all the tr's in the table regardless of whether it has an a descendent with the text "Alice".

(B) meanwhile does what I expect in only selecting the trs with a descendents containing the text "Alice".

As an aside question, is there a more elegant way of writing the above?

Upvotes: 0

Views: 703

Answers (2)

Michael Kay
Michael Kay

Reputation: 163312

//a selects all a elements anywhere in the document.

*/a selects all a elements that are grandchildren of the context node.

.//a selects all a elements that are descendants of the context node at any depth

./a (or just a) selects all a elements that are children of the context node.

It's vital to understand the notion of context. In a predicate such as tr[XXXX] the context node for evaluating XXXX is the tr element that you are testing.

Upvotes: 0

Martin Honnen
Martin Honnen

Reputation: 167516

You would need to use //table[@id="xyz"]//tr[.//a[contains(text(), "Alice")]] or //table[@id="xyz"]//tr[descendant::a[contains(text(), "Alice")]] to make sure that in the first expression the path in square brackets is relative to the tr. With your current //tr[//a] inside the predicate the selection //a starts from the document node, the root node, and is not relative to the tr.

Upvotes: 1

Related Questions