Reputation: 197
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 tr
s 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
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
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