Besides syntax error - you need and , i.e. contains(@href,'tags') and not(position()...) - you are trying to understand the subtlety of the definition // .
XPath //a[position() < last()] will not give you every a except the last, it will give you every a that is not the last a inside its corresponding parent element. Since each li contains at most one a , each a is the last a in its corresponding parent, so this test will not contain anything at all.
You can achieve what you want by wrapping most of the expression in parentheses and putting the position check in a separate predicate
(//*[@id="video-tags"]//a[contains(@href,'tags')])[position() < last()]
The brackets cause the final predicate to be applied to the node set selected by the expression as a whole, and not just to the location step a , that is, it will first find all elements a whose href contains βtagsβ, and then returns everything except the last one these selected items are in document order.
Technical explanation - the // definition in XPath is that it is short for /descendant-or-self::node()/ (including slashes), which is the location step that this node and all of its child nodes give you . So, //a means /descendant-or-self::node()/child::a , and //a[something] means /descendant-or-self::node()/child::a[something] - the predicate is applied to the child:: step, and not to descendant-or-self:: . If you want to apply the predicate to descendants, you must explicitly use the descendant:: - /descendant::a[something] axis.
source share