Using findElements() and size() methods we can get the count.
But I want to extract the count using count() function in the xpath.
Will the count function return an integer value?
Suppose,
My xpath is (//input[#id='stack'])[3] and there are 3 matching nodes with //input[#name='hai']
Can I modify my xpath like below?
(//input[#id='stack'])[count(//input[#name=''hai])]
Yes, if
count(//input[#name='hai'])
evaluates to
3
then
(//input[#id='stack'])[count(//input[#name='hai'])]
will select the same nodes as
(//input[#id='stack'])[3]
would select.
However, your intent is quite unclear, especially given that
//input[#id='stack'] will select all of the input elements with
an id attribute value of 'stack'. Usually id attribute values
are unique across the document, so usually this would select only a
single element.
(//input[#id='stack'])[count(//input[#name='hai'])] assumes that there are at least as many input elements id'ed as 'stack' as there are input elements named 'hai' -- an odd assumption.
driver.findElements() returns a List of WebElements, and .size() returns the integer size of a list, so I think youd be better off doing the following:
int myCount = driver.findElements(By.xpath("<Your Xpath Here>")).size();
This will get you the count of elements on your page that match your xpath input
Related
$x("//div[#class='card-info__container']/div[3]/a")
using this I've found the container, but now I can't get the specific element I need.
when I enter this the response is:
⯆(3) [a.cta.btn, a.cta.btn, a.cta.btn]
⯈0: a.cta.btn
⯈1: a.cta.btn
⯈2: a.cta.btn
how can I take only the first one?
You can use the at() method to select the first item from the array of a that is returned from executing the XPath:
$x("//div[#class='card-info__container']/div[3]/a").at(0)
For an XPath that returns a list of elements,
xpath
you can select only the first element via indexing:
(xpath)[1]
Trying to select the Export button below which has an ID and name. I know I can getelementbyID but not sure how to then specify to further drill into the getattribute("name") because the getelementbyID wil only return 1 value, not an array
Thanks!
#Mturks83
getElementsByName("export")(0) the first part will give you the array of elements called export the (0) gives you the first.
It is faster to use querySelector than getElementsBy.
For example, just got direct with an attribute = value selector
ie.document.querySelector("[name=export]")
If more than one then add the parent td element id
ie.document.querySelector("#bottomButtonRow [name=export]")
Reading:
css selectors
I am trying to create an xpath with using (and) and (or) both expression together but not getting success.
I want to grab prices of products but some prices comes as .//p/span[#class='currency-value'] while other comes as .//p/span/span[#class='currency-value'] so I want to use OR exprssion for this
And I don't want price where product is for Advertise so I am using .//span[not(contains(text(),'Ad'))]
I have tried below xpath but its not working.
.//p/span[#class='currency-value'] | .//p/span/span[#class='currency-value'] and .//span[not(.='Ad')]
Rather than saying "try XXX" I think it's useful if you understand what's wrong with your current attempts.
.//p/span[#class='currency-value'] | .//p/span/span[#class='currency-value'] and .//span[not(.='Ad')]
The "|" operator in XPath means "union" - it forms the union of two node-sets. So //x | //y selects the union of the nodes selected by //x and those selected by //y. So far so good. You can simplify the "union" part of your expression to
(.//p/span | .//p/span/span)[#class='currency-value']
if you want.
The "and" is more problematic. The operands of "and" have to be booleans, whereas in your expression both operands are node-sets. I suspect (though I can't be sure) that your intent is to exclude from the union node-set those nodes that satisfy the predicate .='Ad' but without seeing your source data it's not clear how the products and prices relate to each other. Perhaps you intended this:
(.//p/span | .//p/span/span)[#class='currency-value'][not(.='Ad')]
or perhaps this:
(.//p/span | .//p/span/span)[#class='currency-value'][not(..='Ad')]
Either way, if I'm right that your intent is to exclude some of the nodes that would otherwise be selected, then an additional predicate is the way to do it.
After looking at the page, this CSS selector will work
div.hide-lg:not([data-behat-search-results-ads-xl]):not(.prolist-row) p > span.currency-value, div.hide-lg:not([data-behat-search-results-ads-xl]):not(.prolist-row) p > span > span.currency-value
Try this one. Do not overcomplicate with //p/span
//span[#class='currency-value'][not(.='Ad')]
Try this one. Combines #Vitaliy's answer with yours:
.//p/span[#class='currency-value'][not(.='Ad')] | .//p/span/span[#class='currency-value'][not(.='Ad')]
Please find the use of AND and OR in xpath as below:
this is the Page html:
<div class="mtlist-tab">
<ul class="wwf-tab-h">
<li class="tab-head">
<li class="tab-head on">
<li class="tab-head">
</ul>
</div>
if you are using AND in xpath where the two elements have same class class name then it will return 2 matching elements.
//li[#class='tab-head' and #class='tab-head']
if you are using AND in xpath where the two elements have different class class name then it will return 0 matching elements.
//li[#class='tab-head' and #class='tab-head on']
if you are using OR in xpath where the two elements have different class class name then it will return 3 matching elements(according to the HTML).
//li[#class='tab-head' OR #class='tab-head on']
I am trying to find a way to return the index of a HTML child tag based on its xpath.
For instance, on the right rail of a page, I have three elements:
//*[#id="ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880"]/div[1]/h4
//*[#id="ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880"]/div[2]/h4
//*[#id="ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880"]/div[3]/h4
Assume that I've found the first element, and I want to return the number inside the tag div, which is 1. How can I do it?
I referred to this previous post (How to count HTML child tag in Selenium WebDriver using Java) but still cannot figure it out.
You can get the number using regex:
var regExp = /div\[([^)]+)\]/;
var matches = regExp.exec("//[#id=\"ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880\"]/div[2]/h4");
console.log(matches[1]); \\ returns 2
You can select preceeding sibling in xpath to get all the reports before your current one like this:
//h4[contains(text(),'hello1')]/preceding-sibling::h4
Now you only have to count how many you found plus the current and you have your index.
Another option would be to select all the reports at once and loop over them checking for their content. They always come in the same order they are in the dom.
for java it could look like this:
List<WebElement> reports = driver.findElements(By.xpath("//*[#id='ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880']/div/h4")
for(WebElement element : reports){
if(element.getText().contains("report1"){
return reports.indexOf(element) + 1;
}
}
Otherwise you will have to parse the xpath by yourself to extract the value (see LG3527118's answer for this).
I have a table that consists of multiple rows that each contain 5 cells, like this:
<tr>
<td></td>
<td>123456</td>
<td>statusText</td>
<td><a>linkText</a></td>
<td>editButton</td>
</tr>
The 123456 could be any string of random letters and numbers. I want to be able to select a link based on the contents of the second cell in the table. I've been trying something like this:
//tr[contains(td, '123456')]
to get me to the cell, but it either returns every row or nothing, depending on how I tweak the xpath.
I've been trying something like this:
//tr[contains(td, '123456')]
to get me to the cell, but it either
returns every row or nothing,
depending on how I tweak the xpath
You get what you asked for. The above XPath expression selects any tr element (row) in the document that has (at least one) td child whose string value contains '123456'.
But you want:
//tr/td[text() = '123456']
this selects every td element (cell) in the document, that has a text node child, whose string value is '123456'.
There can be different variations, depending on whether a td may have more than one text nodes and on whether the white space in a text node should be normalized, but the question doesn't provide any information if any of these apply in this particular case.
I'd research something like //tr[string(td[2]) = '123456']. If this does not work, I'd look up XPath axes.