xpath - axes methods return wrong nodes - xpath

I have noticed that using xpath axes methods sometimes return wrong nodes. I have two examples:
url: "http://demo.guru99.com/v1/"
<tr>
<td align="center">
<img src="../images/1.gif">
<img src="../images/3.gif">
<img src="../images/2.gif">
</td>
</tr>
I can select three img elements by axes methods "//td//child::img". However when I use "//td//following-sibling::img", it can still return the second and third img elements. As far as I know, child and sibling are two different thing, so why this happens?
url: http://demo.guru99.com/selenium/guru99home/
<div class="rt-grid-12 rt-alpha rt-omega" id="rt-feature">
<div class="rt-grid-6 ">
<div class="rt-block">
<h3>
Desktop, mobile, and tablet access</h3>
<ul>
<li>
<p>
Free android App</p>
</li>
<li>
<p>
Download any tutorial for free</p>
</li>
<li>
<p>
Watch video tutorials from anywhere </p>
</li>
</ul>
<p>
<img alt="" src="images/app_google_play(1).png"></p>
</div>
</div>
<div class="rt-grid-5 ">
<div class="rt-block">
<img src="images/logo_respnsivsite.png"><br>
</div>
</div>
</div>
Here, if I use "//div[#id='rt-feature' and (#class='rt-grid-12 rt-alpha rt-omega')]//following-sibling::div", those div elements which should be child elements are still be counted as siblings
Use "//div[#id='rt-feature' and (#class='rt-grid-12 rt-alpha rt-omega')]//parent::div", the self element and its child div elements are all counted as parent.
This cause me a lot of confusion, please help me.

Suggesting that the XPath parser returns the wrong nodes, rather than that you don't understand why it is returning what it does, is starting from the wrong mindset. Unless you know the XPath parser is unreliable, start with the assumption that it is right and your expectations are wrong. Then go to the spec and study the semantics of the expression you have written.
You will find that
//td//following-sibling::img
is an abbreviation for
/descendant-or-self::node()/td/descendant-or-self::node()/following-sibling::img
so you have asked for all the following siblings of all the descendants of all the td nodes, which is exactly what you are getting.
I've come across people who habitually write "//" in place of "/" as a sort of magic fairy dust without having the faintest idea what it means. Don't do it: read the spec.

Related

XPATH Firebug filter does not filter as expected

Basically I have a list of presidents and I am only interested in the Nixon link and not Clinton or Obama.
What I find is that filtering as I have done returns the correct number of presidents (ie 1 in this case) but returns ALL of the a links instead of just the one for Nixon.
HTML:
<div class="headlineBlock">
<h2>Obama</h2>
<p class="tudor"><strong>Conditions:</strong> Always sunny </p>
<table class="resultGrid"><tr> <td class="first">
<h4><a href="http://www.thelinkiwant.com?params" title="Click to view result"</a></h4>
<div class="headlineBlock">
<h2>Nixon</h2>
<p class="nixon"><strong>Conditions:</strong> Sometimes late </p>
<table class="resultGrid"><tr> <td class="first">
<h4><a href="http://www.thelinkiwant.com/?params" title="Click to view result"</a></h4>
<div class="headlineBlock">
<h2>Clinton</h2>
<p class="tudor"><strong>Conditions:</strong> Never rainy </p>
<table class="resultGrid"><tr> <td class="first">
<h4><a href="http://www.thelinkiwant/?params" title="Click to view result"</a></h4>
XPATH:
$x("//div[#class='headlineBlock']/h2[not(contains('|Clinton|Obama|',concat('|',.,'|') ))]//../../table/a/#href")
There are several issues with your example.
There brackets missing after ever single "Click to view result", your "headlineBlock" divs and tables aren't closed, etc. So first you should make sure that your data is well formatted.
W3C's Xml Validator can help with that
Your XPath looks mostly ok, I think the issue is with the // at the end - they are a bit too early. Try this instead:
//div[#class='headlineBlock']/h2[not(contains('|Clinton|Obama|',concat('|',.,'|') ))]/..//a/#href
//div[#class='headlineBlock']
All divs of class headlineBlock ...
/h2[not(contains('|Clinton|Obama|',concat('|',.,'|') ))]
... that don't contain certain terms.
/..
Up one level (now we are at div headlineBlock again)
//a
Any direct descendants of element type a
/#href
H-Ref Attribute

Select visible xpath in list

I am trying to get the error message off of a page from a site. The list contains several possible errors so i can't check by id; but I do know that the one with display:list-item is the one I want. This is my rule but doesn't seem to work, what is wrong with it? What I want returned is the error text in the element.
//*[#id='errors']/ul/li[contains(#style,'display:list-item')]
Example dom elements:
<div id="errors" class="some class" style="display: block;">
<div class="some other class"></div>
<div class="some other class 2">
<span class="displayError">Please correct the errors listed in red below:</span>
<ul>
<li style="display:none;" id="invalidId">Enter a valid id</li>
<li style="display:list-item;" id="genericError">Something bad happened</li>
<li style="display:none;" id="somethingBlah" ............ </li>
....
</ul>
</div>
The correct XPath should be:
//*[#id='errors']//ul/li[contains(#style,'display:list-item')]
After //*[#id='errors'] you need an extra /, because <ul> is not directly beneath it. Using // again scans all underlying elements for <ul>.
If you are capable to not use // it would be better and faster and less consuming.

Select elements which has certain descendent using Xpath

I want to Select all the LI elements which contain SPAN with id="liveDeal152_dealPrice" as descendents. How do i do this with xpath?
Here is a sample html
<ul>
<li id="liveDeal_152">
<p class="price">
<em>|
<span class="WebRupee">₹ </span>
<span id="liveDeal152_dealPrice">495 </span>
</p>
</li>
<li id="liveDeal_152">
<p class="price">
<em>|
<span class="WebRupee">₹ </span>
(price hidden)
</p>
</li>
</ul>
//li[.//span[#id = 'liveDeal152_dealPrice']] should do. Or more verbose but closer to your textual description //li[descendant::span[#id = 'liveDeal152_dealPrice']].
Use this
//li[.//span[#id="liveDeal152_dealPrice"]]
It selects
ALL <li> ELEMENTS
//li[ ]
THAT HAVE A <span> DESCENDANT
.//span[ ]
WITH id ATTRIBUTE EQUAL TO "liveDeal152_dealPrice"
#id="liveDeal152_dealPrice"
That said, it doesn't seem like a very wise element selection, mostly due to the dynamically looking id. If you're going to use it once, it's probably ok, but if you're using it, say, for testing and will reuse it many times, it might cause trouble. Are you sure this won't change when you change your website and/or database?
As a side note:
ul stands for "unordered list"
ol stands for "ordered list"
li stands for "list item"

Xpath: robust path for a locator of an element with 1 sibling and one...cousin?

This is the code:
<li>
<a>
<h1>Quorn Stuk­jes</h1>
<p class="price">
</a>
<form>
<button type="submit">+</button>
</form>
</li>
I want to create a locator that finds the first <h1> that has an sibling element <p> with an attribute "price". Easy so far. But now I also want that <h1> to share its grandparent with a <button> class with the attribute type "submit".
What I created was the following:
//a/p[#class="price"]/preceding-sibling::p/preceding-sibling::h1
I'm wondering if this is the most sensible solution (it does work), or if there is something more elegant and robust.
(//*[form/button[#type = 'submit']]/*[p[#class = 'price']]/h1)[1] should do (assuming a submit button only makes sense in a form parent element).

xPath strange behaviour - selecting ALL elements even if [1] set

today I stumbled upon a very interesting case (at least for me). I am messing around with Selenium and xPath and tried to get some elements, but got a strange behaviour:
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some text
</a>
</div>
</div>
</div>
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some other text
</a>
</div>
</div>
</div>
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some even unrelated text
</a>
</div>
</div>
</div>
This is my data.
When i run the following xPath query:
//div[#class="title"][1]/a
I get as a result ALL instead of only the first one. But if I query:
//div[#class="resultcontainer"][1]/div[#class="info"]/div[#class="title"]/a
I get only the first , not all.
Is there some divine reason behind that?
Best regards,
bisko
I think you want
(//div[#class="title"])[1]/a
This:
//div[#class="title"][1]/a
selects all (<a> elements that are children of) <div> elements that have a #class of 'title', that are the first children of their parents (in this context). Which means: it selects all of them.
The working XPath selects all <div> elements that have a #class of 'title' - and of those it takes the first one.
The predicates (the expressions in square brackets []) are applied to each element that matched the preceding location step (i.e. "//div") individually. To apply a predicate to a filtered set of nodes, you need to make the grouping clear with parentheses.
Consequently, this:
//div[1][#class="title"]/a
would select all <div> elements, take the first one, and then filter it down futher by checking the #class value. Also not what you want. ;-)

Resources