xpath find element's grandparent - xpath

I'm a bit stuck with getting a grandparent element by Xpath. Unfortunately, my tries were unsuccessful.
HTML
<span class="fsm fwn fcg">
<a href="bla bla">
<abbr>
<span class="timestampContent" id="js_19">21 mins</span>
</abbr>
</a>
</span>
i need to get the <a href="bla bla"> element as the grandparent for <span class="timestampContent" id="js_19">21 mins</span>
i tried something like the following:
//span[#class='timestampContent' and contains(text(), 21 mins)]../.. or
../..//span[#class='timestampContent' and contains(text(), 21 mins)]
and some other options, but it didn't work as I expected.

Your first try is close, only a / before .. was missing (and missing quotes around '21 mins', which I believe was just a typo) :
//span[#class='timestampContent' and contains(text(), '21 mins')]/../..
Alternatively, you can do it the other way around i.e by selecting element that has grand child span of certain criteria :
//*[*/span[#class='timestampContent' and contains(text(), '21 mins')]]

You need to enclose text in quotes, and a / must come between the ] and the ..:
//span[#class='timestampContent' and contains(text(), '21 mins')]/../..
However, a perhaps more reliable way to achieve this in case the markup changes in future, is to not explicitly go up two levels but to find the first grandparent a tag:
//span[#class='timestampContent' and contains(text(), '21 mins')]/ancestor::a[1]

You could try
//span[#class='timestampContent' and contains(text(), '21 mins')]/../parent::a
This is a more direct way to the a element you want so you won't need to add [1] or [#href='bla bla'] like when using ancestor.
This could be helpful when pointing to a specific div element directly without needing to specify its attributes.

//span[#class='timestampContent' and contains(text(),'21 mins')]/ancestor::a[#href='bla bla']
Here "and" condition makes the element more specified. You are specifically looking for an element that has the specific href('bla bla'). If you want to find the specific element ,which is a parent of a specific child, you use the ancestor:: command.

Related

Xpath Index wont work

I need the third image with that class and parent. None of these xpaths seem to be valid.
xpath=(//div[#class='itemTileV5'])//img[#class='dealItem']/#src[3]
xpath=(//div[#class='itemTileV5']//img[#class='dealItem'])/#src[3]
xpath=(//div[#class='itemTileV5']//img[#class='dealItem']/#src)[3]
Notice I move the parentheses around and it's always an invalid path. Without parentheses it won't work either.
Please help.
<div class="itemTileV5">
<div class="top">
<a href="/Grocery_deals/p_pepperidge-farm-goldfish-variety-pack-bold-mix-29-4-ounce">
<img class="Item" src="https://img.google.com/ai/184x184/dealimage/1493649114.jpg" alt="Pepperidge Farm">
</a>
</div>
</div>
All three of your expressions are valid in all versions of XPath. If you're getting an error, please tell us what it is, and what XPath processor generated it.
The first two expressions aren't useful, because #src[3] selects the third attribute called "src" and there can only be one attribute with a given name.
Your informal requirement "the third image with that class and parent" seems to translate to (//div[#class='itemTileV5']/img[#class='dealItem'])[3]/#src

Xpath not contains

Is there a way to select the xpath which doesn't contain ng-show
Please find the xpath below:
I'm familiar with not(contains()), but it has 2 parameters.
I would like it to not contain the ng-showitself, because I have a few more element containing ng-show and I don't want to select any of them.
<span ng-show="displayValue" class="ng-binding">0 km</span>
Thanks in Advance
Try this below xpath
//span[not(#ng-show)][not(#class='percent ng-binding')][#class='ng-binding']
Explanation of xpath:- Only those <span> tag will return, which attribute does not contains ng-show

Xpath - Find span, exclude child i attribute

Given the following object:
<span id="PartComment">
REMAN WATER PUMP
<i>w/2.05" DIAMETER THERMOSTAT OUTLET - SUPPLIED w/PULLEY
</i>
</span>
I'm trying to come up with an xpath that should locate me only the span by id and the text inside it (REMAN WATER PUMP). Unfortunately, the text inside the i is also caught up.
I was thinking of something like:
//span[#id='PartComment'][not(self::i)]
But it keeps selecting the i text too.
Thanks for stopping by!
Try this:
//span[#id='PartComment']/text()

How to access second element using relative Xpath

Given this page snippet
<section id="mysection">
<div>
<div>
<div>
<a href="">
<div>first</div>
</a>
</div>
<div>
<a href="">
<div>second</div>
</a>
</div>
</div>
</div>
</section>
I want to access the second a-element using relative Xpath. In FF (and locating with Selenium IDE) this
//section[#id='mysection']//a[1]
works but this does not match
//section[#id='mysection']//a[2]
What is wrong with the second expression?
EDIT: Actually I do not care so much about Selenium IDE (just use it for quick verification). I want to get it going with selenium2library in Robot Framework. Here, the output is:
ValueError: Element locator with prefix '(//section[#id' is not
supported
for the suggested solution (//section[#id='mysection']//a)[2]
You can use this. This would select the anchor descendants of section and get you the second node. This works with xslt processor, hope this works with Selenium
//section[#id='mysection']/descendant::a[2]
Try this way instead :
(//section[#id='mysection']//a)[2]
//a[2] looks for <a> element within the same parent. Since each parent <div> only contains one <a> child, your xpath didn't match anything.
With this:
//section[#id='mysection']//a[1]
you are matching all first 'a' elements within any context (inside one div, for example), but with this
//section[#id='mysection']//a[2]
you are trying to match any second 'a' element with any context, but you dont have more than one 'a' element in any of nodes.
The icrementing sibling node thus should be a parent div node to those 'a' tags.
Very simple:
//section[#id='mysection']//a[1] - both elements
This is why previous answer with paranthesis around the whole thing is correct.
//section[#id='mysection']//div[1]/a - only first element
//section[#id='mysection']//div[2]/a - only second elemnt
Other way to mach each 'a' separately:
//section[#id='mysection']//a[div[text()='first']]
//section[#id='mysection']//a[div[text()='second']]
Other ways to reach to the second a-element can be by using the
<div>second</div>, call this bottom-up approach
instead of starting from section-element
<section id="mysection">, call this top-down approach
Using the div child of a-element, the solutions should look like this:
//div[.='second']/..

selenium find child's child elements

I have following html like:
<form name="form1">
<input name="a" ...>
<input name="b" ...>
...
<div><span><select name="c">...</select></span></div>
</form>
I would like to find out all elements within the form element. First I use findElement() to get the form element form1, then use form1.findElements(By.xpath(".//*[#name]")) to get all its children having attribute name. However, for the select element, since it's grand-grand child of form1, how can I get it as well?
Is there a way to find all elements containing attribute name (not only child elements, but also child's child's child...) within form1?
Thanks!
if you want to get an WebElement by xpath, and so get child of it... you may use webElement.findElement(By.xpath("./*")) ... this "." before the "/" makes the magic, you'll need it to get only the children of the webElement...
Do you have to find the form element? If not, then you can do it in one select statement using css or xpath.
The css would be 'form[name="form1"] [name]'
Note the space between the closing and opening brackets.
You would use this selector with FindElement on the driver object rather than finding the form first.
You should be able to use the descendant:: as described in this post.
http://hedleyproctor.com/2011/05/tutorial-writing-xpath-selectors-for-selenium-tests/
Here are a few examples from the article:
//div[h3/text()='Credit Card']/descendant::*
//div[h3/text()='Credit Card']/descendant::input[#id='cardNumber']
//div[*/text()='Credit Card']/descendant::input[#id='cardNumber']
webDriver.findElement(
By.xpath("//div[*/text()='Credit Card']/descendant::input[#id='cardNumber']")
).sendKeys("1234123412341234");

Resources