XPath "and" Confusion - xpath

I recently started a new job that uses cucumber/Gherkin along with selenium. I was trying to create a XPath for a specific element. The xml looks slightly like this...
<p>
<div class="slds-text-title_bold slds-m-bottom_x-small ncc-input-label">
Amp
</div>
<div class="slds-text-title_bold slds-m-bottom_x-small ncc-input-label required-field-label">
Voltage
</div>
</p>
I am looking to only get the div with the required field label in the class and text of "Voltage" So far this kinda works...
//div[contains(text(), "Voltage")] | //*[contains(class, "required-field-label")]
however I'm getting way too many false positives. Any time I change the pipe into "and" I get nothing. What am I doing wrong?
HCSloan

Try the following expression on your actual code, and see if it works:
//div[contains(#class, "required-field-label")][contains(text(), "Voltage")]

You can match the element using "and" like this:
//div[contains(#class, 'required-field-label') and contains(text(), 'Voltage')]

Related

How to exclude a child node from xpath?

I have the following code :
<div class = "content">
<table id="detailsTable">...</table>
<div class = "desc">
<p>Some text</p>
</div>
<p>Another text<p>
</div>
I want to select all the text within the 'content' class, which I would get using this xPath :
doc.xpath('string(//div[#class="content"])')
The problem is that it selects all the text including text within the 'table' tag. I need to exclude the 'table' from the xPath. How would I achieve that?
XPath 1.0 solutions :
substring-after(string(//div[#class="content"]),string(//div[#class="content"]/table))
Or just use concat :
concat(//table/following::p[1]," ",//table/following::p[2])
The XPath expression //div[#class="content"] selects the div element - nothing more and nothing less - and applying the string() function gives you the string value of the element, which is the concatenation of all its descendant text nodes.
Getting all the text except for that containing in one particular child is probably not possible in XPath 1.0. With XPath 2.0 it can be done as
string-join(//div[#class="content"]/(node() except table)//text(), '')
But for this kind of manipulation, you're really in the realm of transformation rather than pure selection, so you're stretching the limits of what XPath is designed for.

Obtain an xpath element containing another element with an specific class

Hello I have this HTML:
<div class="_3Vhpd"><span>Your commerce Data</span>
<a class="n3G0C" href='http://www.webadress.......'><span>Some Text</span</a>
</div>
I tried to obtain the tag as follow:
parser.xpath('//div[contains(#class,"_3Vhpd")]//following-sibling::*[a[#class="n3G0C"]]/#href ')
but I received none '[]'. Maybe because is not just after div but after a span...
First, you sample html doesn't have a class="n3G0C", but assuming you fix it, this xpath expression should work:
//div[contains(#class,"_3Vhpd")]//following-sibling::a/#href
Output:
http://www.webadress.......

Xpath get element above

suppose I have this structure:
<div class="a" attribute="foo">
<div class="b">
<span>Text Example</span>
</div>
</div>
In xpath, I would like to retrieve the value of the attribute "attribute" given I have the text inside: Text Example
If I use this xpath:
.//*[#class='a']//*[text()='Text Example']
It returns the element span, but I need the div.a, because I need to get the value of the attribute through Selenium WebDriver
Hey there are lot of ways by which you can figure it out.
So lets say Text Example is given, you can identify it using this text:-
//span[text()='Text Example']/../.. --> If you know its 2 level up
OR
//span[text()='Text Example']/ancestor::div[#class='a'] --> If you don't know how many level up this `div` is
Above 2 xpaths can be used if you only want to identify the element using Text Example, if you don't want to iterate through this text. There are simple ways to identify it directly:-
//div[#class='a']
From your question itself you have mentioned the answer for it
but I need the div.a,
try this
driver.findElement(By.cssSelector("div.a")).getAttribute("attribute");
use cssSelector for best result.
or else try the following xpath
//div[contains(#class, 'a')]
If you want attribute of div.a with it's descendant span which contains text something, try as below :-
driver.findElement(By.xpath("//div[#class = 'a' and descendant::span[text() = 'Text Example']]")).getAttribute("attribute");
Hope it helps..:)

Hidden XPATH to find element of text? Ruby-selenium

I am trying to find the xpath of the element below, so that I can later get the text using Ruby Selenium-webdriver (ie. helloPage.mainHeader.get_text).
<div class="container">
<div class="template-section">
<div class="front">
<h3 class="containerHeading">
<i class="icon_image"></i>
"Hello world <-----------------------3 whitespaces
"
</h3>
</div>
</div>
</div>
I've worked on xpaths but everytime I rerun the test it timesout essentially the element does not exist. It is clearly visible on the UI and not hidden.
Why is my xpath is wrong? I have tried the following:
//div[#class='container']//div[#class='template-section']//div[#class='front']//h3[#class='containerHeading']
//div[#class='front']//h3[#class='containerHeading']
//h3[#class='containerHeading']
I did put sleep prior to executing helloPage.mainHeader.get_text, where mainHeader has the XPath expression, and that didn't work. Is there something mysterious about the Hello World text? The format is indeed like the way I typed it out.
all your xpaths seems correct to me... I think when you are trying to find the element using your xpath ... the element is not loaded properly... try to use explicit wait. Please try to use the code provided below:
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until { driver.find_elements(:xpath, "Any of your above mentioned xpaths") }

How to check of a Node is inside a form tag?

Using XPath, how do I determine if a node is within a form tag? I guess I am trying to locate the form tag of its ancestor/preceding (but I couldn't get it to work).
example 1:
<form id="doNotKnowIDofForm">
<div id="level1">
<span id="mySpan">someText</span>
</div>
</form>
example 2:
<form id="doNotKnowIDofForm">
This is a closed form.
</form>
<div id="level1">
<span id="mySpan">someText</span>
</div>
</form>
I can use xpath "//span[id='mySpan']" to locate the span node. But I would like to know if mySpan is inside a form (I do not know the id of the form). I have tried "//span[id='mySpan']/preceding::form/" and "//span[id='mySpan']/ancestor::form/"
Thanks in advance.
EDIT: I would like the XPath to select the myForm form tag in Example1 but NOT in Example2
I'm not 100% sure from your description whether you're looking to select the form element, or the span element. It seems more likely that you're going for the form, so I'll address that first.
Your XPath with the ancestor::form would have been ok if it didn't have the slash at the end, but it's more roundabout than it needs to be. I think this is a better way:
//form[.//span/#id = 'mySpan']
or this:
//form[descendant::span/#id = 'mySpan']
To produce an XPath that locates certain nodes only if they are within a form, you would put the ancestor::form inside the predicate:
//span[#id = 'mySpan' and ancestor::form]
or you can do this, which would again be more straightforward:
//form//span[#id = 'mySpan']
Your own attempt
//span[id='mySpan']/ancestor::form/
looks fine to me.
You can simply use,
"form//span[id='mySpan']"

Resources