xpath: find element by text between tags - selenium

We can find element by inner text, for example:
<span>
<div>
Example Text
</div>
<div>
Other Text
</div>
</span>
In this case we can use follow xpath: //span/div[contains(text(), 'Example')]
But how can I found element when the text exist out of the tag?
For example:
<span>
<div id="1">
...........
</div>
Example Text
<div id="2">
......
</div>
Other Text
</span>
And shat if, I haven't id on the div tags, and I can't use order?
<span>
...........
<div>
...........
</div>
Example Text
<div>
......
</div>
Other Text
</span>

You can use xpath axes to select siblings.
//text()[contains(.,"Example")]//preceding-sibling::div[1]

You can use this XPath
//span[contains(text(),'Example Text')]//div[#id='1']
For the first div.
The same for the second div
//span[contains(text(),'Example Text')]//div[#id='2']
Generally, in this case the "Example Text" text is contained by the parent span element.
So you can locate the parent span according to this text and then drill down to the child div.

Related

How to select the div tag with the value of text node of label tag

<abc>
<div>
<input>
<label>A
<span>C</span>
</label>
</div>
<div>
<input>
<label>AB
<span>D</span>
</label>
</div>
</abc>
I need to select the <div> tag with search criteria of text in the <label> tag. Text inside <span> is dynamic and sometimes it is empty, so this should not be used as search criteria.
What I have so far tried is below, both could not return the answer:
//div[./label[.='A']]
//div[./label[text().='A']]
One way to do it with ancestor (first will select div with label "A", second will select div with label "AB") :
//label[./text()[normalize-space()="A"]]/ancestor::div
//label[./text()[normalize-space()="AB"]]/ancestor::div
With contains function :
//label[contains(./text(),"A") and string-length(normalize-space(./text()))=1]/ancestor::div
//label[contains(./text(),"AB")]/ancestor::div
Use parent:
//label[text()='A']//parent::div
Also you can use text contains:
//label[contains(text(),'A')]//parent::div
To select the parent <div> element with respect to it's child <label> element's text using Selenium you can use the following xpath based Locator Strategies:
Selecting <div> with child <label> text as AB
//div[//label[contains(., 'AB')]]
Note: selenium still doesn't supports xpath-2.0 so you have to use xpath-1.0

How can I find out what number in <ul> some <li> element is? In Selenium

I have a < ul > with unknown number of < li > elements. Each < li > has some text and also a button. How can I identify which < li > contains the text I'm looking for, in order to click the button in that same < li >?
<ul>
<li class="ot-queryitem row-fluid">
<div class="ot-queryitem__info ot-queryitem__info--left span7">
<span class="ot-queryitem__name">Äänikysely (Voice Activity and Participation Profile)</span>
</div>
<div class="ot-queryitem__info ot-queryitem__info--center span3"></div>
<div class="ot-queryitem__info ot-queryitem__info--right span2">
<button class="ot-button ot-button--undefined pull-right ot-queryitem__button">
<i class="icon-pencil fa ot-icon ot-icon--default" style="margin-right: 8px;"></i>
<span>Täytä</span>
</button>
<span class="ot-queryitem__logo"></span></div></li>
<li class="ot-queryitem row-fluid">
<div class="ot-queryitem__info ot-queryitem__info--left span7">
<span class="ot-queryitem__name">Nikotiiniriippuvuustesti</span>
</div>
<div class="ot-queryitem__info ot-queryitem__info--center span3"></div>
<div class="ot-queryitem__info ot-queryitem__info--right span2">
<button class="ot-button ot-button--undefined pull-right ot-queryitem__button">
<i class="icon-pencil fa ot-icon ot-icon--default" style="margin-right: 8px;"></i>
<span>Täytä</span>
</button>
<span class="ot-queryitem__logo"></span></div></li>
//span[text()='Nikotiiniriippuvuustesti'] will give you a <span> with the given text
/ancestor::li axis will give you the parent <li> tag
/descendant::button axis will give you the <button> you're looking for
Putting everything together:
//span[text()='Nikotiiniriippuvuustesti']/ancestor::li/descendant::button
Demo:
References:
XPath Tutorial
XPath Axes
XPath Operators & Functions
Try the following xpath.
xpath: //ul//li[contains(.,'Nikotiiniriippuvuustesti')]//button
OR
xpath: //ul//li[contains(.,'Äänikysely')]//button
However You can pass this Nikotiiniriippuvuustesti or Äänikysely as string variable in robotframework.Hope this helps.
Both the element with the text and the button are child elements under each <li>. You need to go up the html tree from the text and then look for a button under a sibling element
//div[span[contains(., 'Äänikysely')]]/following-sibling::div/button
To identify li tag which contains text you looking for as -
${YOUR_TEXT} Nikotiiniriippuvuustesti
## this keyword will give first matching element
${elements}= Get WebElement xpath://span[contains(text(),'${YOUR_TEXT}')]/ancestor::li
### wait for element to be present on page
Wait Until Page Contains Element ${elements}
## now click on button inside li tag found in above lines
Click Button xpath://span[contains(text(),'${YOUR_TEXT}')]/ancestor::li//button
note: locators are taken from the html sample you provided
You don't have to count the number of <li> within the <ul>.
To click on the respective button according to the text e.g. Äänikysely, Nikotiiniriippuvuustesti etc you can use the following solution:
To click for Äänikysely:
Click Button xpath://div[contains(#class, 'ot-queryitem__info--left')]/span[contains(.,'Äänikysely')]//following::button[#class='ot-button ot-button--undefined pull-right ot-queryitem__button']//span[text()='Täytä']
To click for Nikotiiniriippuvuustesti:
Click Button xpath://div[contains(#class, 'ot-queryitem__info--left')]/span[contains(.,'Nikotiiniriippuvuustesti')]//following::button[#class='ot-button ot-button--undefined pull-right ot-queryitem__button']//span[text()='Täytä']

Xpath for div with span having a css class get its sibling anchor link

I want all div's anchor link whose span having css class ='block-diff-neutral'
<div class="file-info" xpath="1">
<span class="diffstat tooltipped tooltipped-e" aria-label="0 ">
<span class="block-diff-deleted"></span>
<span class="block-diff-deleted"></span>
<span class="block-diff-neutral" style=""></span>
<span class="block-diff-neutral"></span>
<span class="block-diff-neutral"></span>
</span>
someText
</div>
<div class="file-info" xpath="1">
<span class="diffstat tooltipped tooltipped-e" aria-label="0 ">
<span class="block-diff-deleted"></span>
<span class="block-diff-deleted"></span>
</span>
someText2
</div>
Here div contains 2 subtags i.e. span and a
if span contains a css class as 'block-diff-neutral' only then get the a tag's title attribute => xpath with this condition is required
Expected output is => someText or file1
Your markup looks invalid (it's missing some closing tags) and it looks over convoluted in places (multi-layered <span> tags).
However this should do what you want if I've understood your requirements correctly.
//div[#class="file-info"][./descendant-or-self::span[#class="block-diff-neutral"]]/a
if the span with a missing closing tag is actually a parent of the anchor this would be better:
//div[#class="file-info"][./descendant-or-self::span[#class="block-diff-neutral"]]/descendant-or-self::a
This will find a div with a class of file-info that has a descendent <span> element with the class block-diff-neutral and then find the anchor inside that div element.
To get the title attribute out of the WebElement you would find with this XPath you will need to use .getAttribute("title")
Try the following Xpath.
//span[#class='block-diff-neutral']/parent::span/parent::div/a
Or use following sibling
//span[#class='block-diff-neutral']/parent::span/following-sibling::a
If you are using python use following code and use any of the xpath locator above.
driver.find_element_by_xpath("//span[#class='block-diff-neutral']/parent::span/parent::div/a").text
driver.find_element_by_xpath("//span[#class='block-diff-neutral']/parent::span/parent::div/a").get_attribute("title")
If you are using java try below code and any locator mentioned above.
driver.findElement(By.xpath("//span[#class='block-diff-neutral']/parent::span/following-sibling::a").getText()
driver.findElement(By.xpath("//span[#class='block-diff-neutral']/parent::span/following-sibling::a").getAttribute('title')

Customize selection for collection of elements - Selenide

How can I select the on of element, and this element contains a collection of elements, How can I select or pass through this element's collection?
the default search method WebDriverRunner.getWebDriver().findElements(By.tagName("*"));
is $$("*")
they consider that default space to search is the whole document, how can I specify the region to search? Assume that I need the a tags from the region or from specific element.
I have the following schema for my page:
<div class="class1">
<a href="" />
<a href="" />
<img src="img.png" />
</div>
<a href="" />
<a href="" />
<div class="class2">
<a href="" />
<div class="class4"> <div>
</div>
How can I pass all elements of div class="class1", ex: after select div.class1 element, I need to see all elements inside this div.
You should find first div class="class1" then using this object find all element under this like below code:
WebElement el = WebDriverRunner.getWebDriver().findElement(By.className("class1"));
List<WebElement> elements = el.findElements(By.tagName("*"));
Let me know if this will not work!!!
Thanks
Sadik

xpath not finding text inside <div><span>

.//*[contains(text(), "Apply")]
<input type="hidden" value="false" name="needsValidation"/>
<input type="hidden" value="false" name="fullValidationPerformed"/>
<div class="loadingBox hidden">
<div class="paneContent">
<div class="topButtons">
<div class="rightSide">
<div id="saveChangesButton" class="majorButton">
<div>
<div>
<div>
<span class="hidden"/>
Apply Changes
<span class="down"/>
</div>
</div>
</div>
</div>
</div>
Why is it that the xpath string I created doesn't find "Apply" here? It appears that my xpath statement only fails when the text I want to find is inside a "span" tag inside a "div" tag like this.
Can someone help me understand what I'm missing here please?
The reason that contains(text(), 'Apply') does not work is that the element has several text nodes, and the contains function in XPath 1.0 ignores all but the first. (XPath 2.0 would give you an error if there is more than one).
If you want to get an element whose string value contains 'Apply' without also returning its ancestors, the simplest way is to get the last element containing this string:
(//*[contains(., 'Apply')])[last()]