⬆️ ⬇️

Three rarely used axes in XPath

The main strength of the XPath language lies in the axes that allow you to get to any element in the original document. Consider the use of such rarely used axes as ancestor , descendant, and self .



ancestor



Task: get the id attribute of the element “great-grandfather” foo.



Usually in such cases, the stairs begin to draw:

')

../../../@id



Such a record is bad in that it is obscure without knowing the source xml. The author recommends in such cases to use a more informative expression:



ancestor::foo[1]/@id



This record not only gives an idea of ​​the item you are looking for, but also continues to work even if the current item has changed its position in the tree.



descendant



Task: find the first descendant of foo in the current element.



When a similar question was asked on StackOverflow.com, two people immediately answered .//foo[1] and were supported by other participants. The author had to intervene and warn about the incorrectness of this expression. The correct answer: descendant::foo[1] , and here's why.



.//foo is a short form of the following expression:



self::node()/descendant-or-self::node()/child::foo



The entry .//foo[1] means all descendants of foo, each of which is the first foo of its parent . Such an expression will return two elements in the following document:



  <list>
     <item> <foo /> </ item>
     <item> <foo /> </ item>
 </ list> 


descendant::foo[1] returns exactly one item.



This distinction is described in the documentation, but for some reason many people read it inattentively. To avoid mistakes, the author recommends that you always write descendant::foo instead of .//foo , since in most cases this is what is meant.



self



It would seem, why do you need self, if there is a shorter version:. (point). However, this axis also found its application.



Task: get the next element if it is called foo.



The obvious solution:



following-sibling::*[1][name() = 'foo']



More elegant, in the opinion of the author, the expression:



following-sibling::*[1]/self::foo



Comments and additions are welcome.

Source: https://habr.com/ru/post/52680/



All Articles