I have tried below Xpath but it's not working for the mentioned element
//span[#text(),'Accounts')]
//span[Contains(#text() ='Accounts']
//span[text()='Accounts'][1]
#text() is syntactically valid but will never select anything - you're looking for text nodes on the attribute axis, and the only thing ever found on the attribute axis is an attribute node. (When I see this kind of construct, I get the impression you're groping in the dark, and haven't found a decent reference that you can consult.)
//span[text()='Accounts'] will select the required node, but it isn't the first child of its parent, so adding the predicate [1] causes it to be rejected.
You want (//span[text()='Accounts'])[1].
Related
I am trying to quickly find a specific node using XPath but it seems my multiple predicates are not working. The div I need has a specific class, but there are 3 others that have it. I want to select the fourth one so I did the following:
//div[#class='myCLass' and 4]
However the "4" is being ignored. Any help? I am new to XPath.
Thanks.
If a xpath query returns a node set you can always use the [OFFSET] operator to access a certain element of it.
Use the following query to access the fourth element that matches the #class='myClass' predicate:
//div[#class='myCLass'][4]
#WilliamNarmontas answer might be an alternative to the syntax showed above.
Alternatively,
//div[#class='myCLass' and position()=4]
The accepted answer works correctly only if all of the div elements have the same parent. Otherwise use:
(//div[#class='myCLass'])[4]
I am trying to find XPath of an element which has no attribute. It can only be identified by its parent's attribute. However, the parent also does not have unique attribute.
Eg: //*[#id="btn"][1]/ul/li[2]/a/span
Here there are 2 elements with id=btn. How do i get the 2nd element. The above syntax gives me 1st element.. However if i use:
//*[#id="btn"][2]/ul/li[2]/a/span
I get an error message
"The xpath expression '//*[#id="btn"][2]/ul/li[2]/a/span' cannot be evaluated or does not result in a WebElement "
Try this, you select those two first, then use brackets around and index them.
(//*[#id="btn"]/ul/li[2]/a/span)[2]
By the way, it's not a good practice to have multiple elements sharing same ids, if you are the developer, may consider change them.
Edit: I think I found the answer but I'll leave the open for a bit to see if someone has a correction/improvement.
I'm using xpath in Talend's etl tool. I have xml like this:
<root>
<employee>
<benefits>
<benefit>
<benefitname>CDE</benefitname>
<benefit_start>2/3/2004</benefit_start>
</benefit>
<benefit>
<benefitname>ABC</benefitname>
<benefit_start>1/1/2001</benefit_start>
</benefit>
</benefits>
<dependent>
<benefits>
<benefit>
<benefitname>ABC</benefitname>
</benefit>
</dependent>
When parsing benefits for dependents, I want to get elements present in the employee's
benefit element. So in the example above, I want to get 1/1/2001 for the dependent's
start date. I want 1/1/2001, not 2/3/2004, because the dependent's benefit has benefitname ABC, matching the employee's benefit with the same benefitname.
What xpath, relative to /root/employee/dependent/benefits/benefit, will yield the value of
benefit_start for the benefit under parent employee that has the same benefit name as the
dependent benefit name? (Note I don't know ahead of time what the literal value will be, I can't just look for 'ABC', I have to match whatever value is in the dependent's benefitname element.
I'm trying:
../../../benefits/benefit[benefitname=??what??]/benefit_start
I don't know how to refer to the current node's ancestor in the middle of
the xpath (since I think "." at the point I have ??what?? will refer to
the benefit node of the employee/benefits.
EDIT: I think what I want is "current()/benefitname" where the ??what?? is. Seems to work with saxon, I haven't tried it in the etl tool yet.
Your XML is malformed, and I don't think you've described your siduation very well (the XPath you're trying has a bunch of ../../s at the beginning, but you haven't said what the context node is, whether you're iterating through certain nodes, or what.
Supposing the current context node were an employee element, you could select benefit_starts that match dependent benefits with
benefits/benefit[benefitname = ../../dependent/benefits/benefit/benefitname]
/benefit_start
If the current context node is a benefit element in a dependents section, and you want to get the corresponding benefit_start for just the current benefit element, you can do:
../../../benefits/benefit[benefitname = current()/benefitname]/benefit_start
Which is what I think you've already discovered.
I have several nodes with some particular attribute and I need to select one of them by index. For example I need to select second <div> with 'test' class - //div[#class='test'][2] doesn't work.
Is there a way to select node with some attribute by index ? How to do it?
This is a FAQ.
In XPath the [] operator has a higher precedence (binds stronger) than the // pseudo-operator.
Because of this, the expression:
//div[#class='test'][2]
selects all div elements whose class attribute is "test" and who (the div elements) are the second such div child of their parent. This is not what you want.
Use:
(//div[#class='test'])[2]
I believe per XML specification, attributes are not considered to have an order.
Note that the order of attribute specifications in a start-tag or empty-element tag is not significant.
See here
I think you'd be best of re-factoring your structure such that attribute order does not describe anything. If you can give any more details we might be able to offer suggestions.
EDIT: Re-reading your post, looks like you are trying to find node order and not attribute order. Node order is allowed and your syntax looks OK off-hand. What software are you doing this in?
What is the XPath to find only ONE node (whichever) having a certain attribute (actually I'm interested in the attribute, not the node). For example, in my XML, I have several tags having a lang attribute. I know all of them must have the same value. I just want to get any of them.
Right now, I do this : //*[1][#lang]/#lang, but it seems not to work properly, for an unknown reason.
My tries have led me to things ranging from concatenation of all the #lang values ('en en en en...') to nothing, with sometimes inbetween what I want but not on all XML.
EDIT :
Actually //#lang[1] can not work, because the function position() is called before the test on a lang attribute presence. So it always takes the very first element found in the XML. It worked best at the time because many many times, the lang attribute was on root element.
After some more tackling, here is a working solution :
(//#lang)[1]
Parentheses are needed to separate the [1] from the attribute name, otherwise the position() function is applied within the parent element of the attribute (which is useless since there can be only one attribute of a certain name within a tag : that's why //#lang[2] always selects nothing).
Did you tried this?
//#lang[1]
here you can see an example.
The following XPath seems to do what you want:
//*[#lang][1]/attribute::lang