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>
Let us consider an example in which we will try to locate the last text field on the Google sign-up page i.e. "Confirm Password" field. Using XPath- last() method, we can write the Java code along with the dynamic XPath location as: findElement(By. xpath("(//input[@type='text'])[last()]"))
The xpath of captured object always changing dynamically based on time of execution in milliseconds. So, every time page opening or reloading changes to object xpath. “Spy” and “Recorder” tools are short for Web pages with dynamic id attributes.
At times, XPath may change dynamically and we need to handle the elements while writing scripts. The standard way of writing XPath may not work and we need to write dynamic XPath in selenium scripts.
XPath is a technique in Selenium to navigate through the HTML structure of a page. XPath enables testers to navigate through the XML structure of any document, and this can be used on both HTML and XML documents. This post looks at various ways to use the XPath element in Selenium to select various elements.
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:
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 //
.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With