Select preceding-sibilings of element that contains child in xpath - xpath

I have code that looks like this
<div id="content">
<p>text</p>
<p>text1</p>
<p>text3</p>
<p><iframe></iframe></p>
<p>text4</p>
<p>text5</p>
</div>
I need to select all "p" elements before "p" that contains child "iframe", I tried something like this
//div[#id='content']//p[iframe]/preceding-sibiling::p
but with no luck.
I am stuck here for a few days so any help would be great.

Your XPath logic was actually fine! You just have a few typos it appears.
//div[#id='content']/p[iframe]/preceding-sibiling::p
You also don't need the extra / after the div block. Here's the full working xpath:
//div[#id='content']/p[iframe]/preceding-sibling::p

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

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']/..

XPath expression -hierarchy

<div class="summary-item">
<label >Price</label>
<div class="value">
0.99 GBP
</div>
</div>
<div class="summary-item">
<label >Other info</label>
<div class="value">
All languages
</div>
</div>
I am trying to get the "0.99 GBP" using an XPath expression, so far I have reached the label using this (note there is another class by the name summary-item, therefore I need to uniquely identify with the label name Price)
sel.xpath('//*/div[#class="summary-item"]/label[text()="Price"]').extract()
However, I am unable to get to the class, I tried using following-sibling, but I did not succeed, any help will be appreciated.
The existence of child nodes can be part of the predicate. Put the test for label into a predicate for the parent, either as a separate predicate (adding the target node as well):
//div[#class="summary-item"][label[text()="Price"]]/div[#class="value"]
or joined with and:
//div[#class="summary-item" and label[text()="Price"]]/div[#class="value"]
(Note you don’t need //*/div at the start.)
You could use following-sibling if you wanted, it would look like this:
//div[#class="summary-item"]/label[text()="Price"]/following-sibling::div[#class="value"]
(here the label div isn’t part of the predicate).
One more thing to be aware of, using XPath to select HTML classes doesn’t work the same as using CSS – XPath will only match the exact string whereas CSS matches even if the element is in more than one class. In this case it works out okay but you should watch out for it. Search StackOverflow if it will be an issue, there are a few answers descibing it.

XPath expression for element based on containing text

I'm running out of ideas. I have identified for my Selenium test an div based on its text ("security administrator ") contained. Unfortunately, the div contains two other divs. See the example.
<div class="rich-stglpanel-marker">
<div class="rich-stglpnl-marker" id="j_id194:j_id198:2:j_id199_switch_on" style="display: none"></div>
<div class="rich-stglpnl-marker" id="j_id194:j_id198:2:j_id199_switch_off"></div>
security administrator
</div>
<div class="rich-stglpanel-marker">
<div class="rich-stglpnl-marker" id="j_id194:j_id198:2:j_id199_switch_on" style="display: none"></div>
<div class="rich-stglpnl-marker" id="j_id194:j_id198:2:j_id199_switch_off"></div>
technical administrator
</div>
... and so on
I tried that expressions:
//div[text()='security administrator']
//div[text()='security administrator ']
//div[text()='security administrator ']
//div[text()='security administrator${nbsp}'] (this is a special hack from selenium)
Nothing works. Any ideas?
Thanks in advance.
Can you try with this :
//div[contains(.,'security administrator')]
System.out.println(driver.findElementByXPath("//div[contains(.,'security adm')]").getText())
gave me security administrator
try this
//div[#class='rich-stglpanel-marker']
Try this: //div[#class='rich-stglpanel-marker' and text()!='']
EDIT
Finally got it!
Use this: //div[#class='rich-stglpanel-marker' and normalize-space(div[last()]/following-sibling::text())='security administrator']
I believe that in this situation, the text "security administrator" is counted as a node, and not as the sole text value of the first div node, which is why //div/text() will give you multiple return lines followed by the text you're searching for, and also why you cannot apply something like normalize-space(),translate(), or even contains() to div/text() and receive results. But, since the text node doesn't have a name, that makes it a funky XPath to figure out, so navigating to the closest possible sibling node was the only option I could think of.

Xpath getting node without node child contents

hey guys coudln't get around this. I have an html structured as follow:
<div class="review-text">
<div id="reviewerprofile">
<div id="revimg"></div>
<div id="reviewr">marc</div>
<div id="revdate">2011-07-06</div>
</div>
this is an awesome review
</div>
what i am trying to get is just the text "this is an awesome review" but everytyme i query the node i also get the other content in the childs. using something like this now ".//div[#class='review-text']" how to get just that text only? tank you very much
You're almost there! Just add /text() at the end of your XPath to get the text node.
An XPath expression such as //div returns a set of nodes, in this case div elements. These are in effect pointers to the original nodes in the original tree; the nodes are still connected to their parents, children, ancestors, and siblings. If you see the children of the div element and don't want them, that's not the fault of the XPath processor, it's the fault of whatever software is processing the results returned by the XPath expression.
You can get the text that's an immediate child of the div element by using /text() as suggested. However, that assumes that you know exactly what you are expecting to find in the HTML page - if "awesome" were in italics, it would give you something different.

Resources