Xpath selects elements except wth last element contain syntax

I want to select the following html elements (action, comedy), but apart from the last (tags).

To select all my code:

//*[@id="video-tags"]//a[contains(@href,'tags')] 

But for the selection, except for the last one (tags), it will not work with my code:

 //*[@id="video-tags"]//a[contains(@href,'tags') not(position() > last() -1)] 

html

 <ul id="video-tags"> <li>Uploader: </li> <li class="profile_name"><a href="/profiles/wilco">wilco</a></li> <li><em>Tagged: </em></li> <li><a href="/tags/action">action</a>, </li> <li><a href="/tags/comedy">comedy</a>, </li> <li>more <a href="/tags/"><strong>tags</strong></a></li> </ul> 

Thank you in advance

Nick

+6
source share
2 answers

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.

+10
source

try it

 (//ul[@id="video-tags"]//a[contains(@href,'tags')]/text()) 
0
source

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


All Articles