I'm trying to locate a web element that have two child nodes as:
<div _ngcontent-c2="" class=" " title="Twelve (Start date is 31| 0 user)" xpath="1"></div>
<div _ngcontent-c2="" class=" " title="Twelve (Start date is 31| 0 user)" xpath="2"></div>
I tried //div[contains(#title,'Twelve (Start date is 31| 0 user)')][1] to get the first element but didn't work for me.
xpath="1"
xpath="1" attribute is the reference of xpath v1.0
xpath="2"
xpath="2" attribute is the reference of xpath v2.0
For the record Selenium supports XPath v1.0 only.
A bit more of the outerHTML including the parent tag would have helped us to construct a more canonical answer. Moreover the information about the Language Binding you are using is also missing. However to locate the first element you need to induce WebDriverWait for the desired visibilityOfElementLocated() and you can use the following can use the following xpath:
Java:
WebElement element = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[contains(#title,'Start date is 31') and #xpath='1']")));
Python:
element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[contains(#title,'Start date is 31') and #xpath='1']")))
Here you can find a detailed discussion on What are the differences between versions of XPath (1.0, 2.0, 3.1)
You can try with CSS:
div[xpath='1']
div[xpath='2']
Related
Quick one, i am trying to avoid using xpath and using css selectors due to performance issues xpath can have so i would like to know the right approach of locating for example "A" in the list
<div class="input-search-suggests" xpath="1">
<div class="input-search-suggests-item">A</div>
<div class="input-search-suggests-item">B</div>
<div class="input-search-suggests-item">C</div>
</div>
Currently i am locating A using xpath / span but it would be indeed sufficient locating all elements and then grabbing A from the list that have same class which is "input-search-suggests-item"
#FindBy(xpath = "//span[contains(text(),'A')]")
CSS_SELECTOR does not have support for direct text what xpath has.
What this means is, for the below xpath
xpath = "//span[contains(text(),'A')]"
based on text A you can not write a css selector.
Instead to locate A using css selector, you can do :
div.input-search-suggests > div.input-search-suggests-item
In Selenium something like this :
#FindBy(cssSelector= "div.input-search-suggests > div.input-search-suggests-item")
Even though it will have 3 matching nodes, but findElement will take the first web element.
Also you may wanna look at nth-child(n)
div.input-search-suggests > nth-child(1)
to make use of index to locate A, B, C
Here is the Reference Link
How to handle multiple xpath for same locator using Selenium, i.e if one is failed use another locator for same field before failing script.
To start with each WebElement within the DOM Tree can be uniquely identified using any of the available Locator Strategies.
However, you can construct multiple xpath for the same element using permutation and combination of the available attributes and their values. As an example, for the element below:
<div class="_2S1VP copyable-text selectable-text" data-tab="1" dir="ltr" spellcheck="true" contenteditable="true"></div>
You can construct multiple xpaths as follows:
"//div[contains(#class, 'copyable-text')]"
"//div[contains(#class, 'copyable-text') and #data-tab='1']"
"//div[contains(#class, 'copyable-text') and #data-tab='1'][#dir='ltr']
"//div[contains(#class, 'copyable-text') and #data-tab='1'][#dir='ltr' and #spellcheck='true']"
"//div[contains(#class, 'copyable-text') and #data-tab='1'][#contenteditable='true']"
All these xpaths would identify the same element. But what matters most is the xpath should be able to identify the desired element uniquely. The responsibility of constructing the optimized xpath is solely on the test creator.
Use OR expression for the same. You can pass multiple attribute of the same WebElement.
For example:
Xpath=//*[#type='submit' or #name='btnReset']
Is parent child relationship valid for cssSelector as well in selenium
Example-
This X-path is valid:
driver.findElement(By.xpath("//div[#class='gb_ke gb_i gb_Kg gb_Ag']/div[2]/a")).click();
But this cssSelector is not:
driver.findElement(By.cssSelector("div[class*='gb_ke gb_i gb_Kg gb_Ag']/div[2]/a")).click();
It gives the error:
An invalid or illegal selector was specified
CSS selectors and XPath selectors have a different syntax.
Your xpath is By.xpath("//div[#class='gb_ke gb_i gb_Kg gb_Ag']/div[2]/a")
and you should update your CSS accordingly, e.g.
CSS By.cssSelector("div[class*='gb_ke gb_i gb_Kg gb_Ag'] div:nth-child(2) a")
To start with xpath and css-selectors follows different syntax.
The equivalent cssSelector locator for the xpath:
driver.findElement(By.xpath("//div[#class='gb_ke gb_i gb_Kg gb_Ag']/div[2]/a")).click();
Can be either of the following as per the prevalent HTML DOM:
driver.findElement(By.cssSelector("div.gb_ke.gb_i.gb_Kg.gb_Ag > div:nth-of-type(2) > a")).click();
Or
driver.findElement(By.cssSelector("div.gb_ke.gb_i.gb_Kg.gb_Ag > div:nth-child(2) > a")).click();
I am inspecting one button element from a web page using chrome driver and selenium. And the html code for the particular button is:
<div class="label text-left text-link link-blue text-
uppercase">Financial Statement Analysis <span class="count">(2)</span>
</div>
I have tried different element options like find element by name, xpath, link text etc. But none of them unable to locate the element.
What will be the element to locate the button. ?
try Xpath :
//span[contains(#class,'count') and text() = '(2)']
You can try with this css selector :
div.label.text-left.text-link.link-blue.text-.uppercase
To locate the element with text as Financial Statement Analysis (2) you can use the following solution:
Java Solution:
WebElement elem = driver.findElement(By.xpath("//div[#class='label text-left text-link link-blue text-uppercase'][contains(.,'Financial Statement Analysis')]"));
how to locate only parent span which is containing the price value from the below Code,locator strategy doesn't matter:
<div class="price-box price-margin">
<p class="old-price"></p>
<p class="special-price">
<span id="product-price-75254" class="price">
56,90 €
<span class="steuerstern">*</span>
</span>
</p>
</div>
The issue is not the selector here. But the text function.
//p[#class="special-price"]/span[#class="price"]
This will select the node, but selenium will always return the node of the child nodes also. What you are looking for is the node text in this case. This can only be done using JavaScript. Since you didn't mention a language I am going to assume python
elem = driver.find_element_by_xpath('//p[#class="special-price"]/span[#class="price"]')
price = driver.execute_script("return arguments[0].firstChild.textContent.trim();", elem)
print(price)
56,90 €
Using selector you can go like this:
".price-box span.price"
Result:
56,90 €
To test the xpath correctness in Chrome you can use
//span[#class="price"]/text()
Since you didn't mention the language you use , here is an example in nightwatchjs with selenium by using .getText()
.getText() is returning an object, the actual text is the value of callback.
var thetext='';
.getText('//span[#class="price"]' ,fucntion(result){
thetext=result.value();
})
As you haven't mentioned the Selenium bindings you are using so I will construct an Answer through Java bindings. Here we will use a customized xpath to locate the node with text 56,90 € with out the * as follows:
WebElement ele = driver.findElement(By.xpath("//p[#class='special-price']/span[contains(#class,'price') and not(#class='steuerstern')]"));