Why is XPath last() function not working as I expe

2020-03-24 06:40发布

I am using Java and Selenium to write a test. I need to get the last element inside another element, so I used last() function, but the problem is that it doesn't always bring me the last one when I apply :

//a//b[last()]

to

 <a> 
   <l>
     <b>asas</b> 
   </l>
   <b>as</b>
 </a> 

to get <b>as</b> ,it brings me:

<b>asas</b>

<b>as</b>

but when I apply it to:

 <a>      
   <b>asas</b> 
   <b>as</b>
 </a>

it brings me:

<b>as</b>

2条回答
等我变得足够好
2楼-- · 2020-03-24 07:03

I think it's easiest to understand the behaviour if you remember that "//" is an abbreviation for "/descendant-or-self::node()/", and that the step "b" is an abbreviation for "child::b". So

//b[last()]

is an abbreviation for

/descendant-or-self::node()/child::b[position()=last()]

Which means "Select every node in the document (except attributes and namespaces). For each of these nodes, form a list of the child elements named "b", and select the last element in this list".

You ask for sources of information. @kjhughes recommends reading the XPath 1.0 recommendation, and indeed, it is a lot more readable than many specs. But it can be a bit terse at times; it occasionally feels like solving a crossword puzzle. My "XSLT 2.0 Programmer's Reference" (which also includes a lot of material on XPath) was written for people who want a deep understanding of how the language works, but explained in plainer English. This particular topic is on page 627, and it's easy enough to find a pirated copy on the web if you want to see how it's covered. But I'd recommend buying a legal copy, because scrolling through 1300 pages of scanned PDF is not much fun.

查看更多
够拽才男人
3楼-- · 2020-03-24 07:26

This is a common source of XPath confusion. First the straightforward parts:

  • //a selects all a elements in the document.
  • //a//b selects all b elements in the document that are descendants of a elements.

Normal stuff so far. Next is the tricky part:

  1. To select the last b elements among siblings (beneath a elements):

    //a//b[last()]
    

    Here, the filtering is a part of the b selection criteria because [] has a higher precedence than //.

  2. To select the last b element in the document (beneath a elements):

    (//a//b)[last()]
    

    Here, the last() is an index on the list of all selected b elements because () is used to override the default precedence.

查看更多
登录 后发表回答