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']
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
I need to detect via xpath an element (image with href) but i know a part of href only
This is the html
<img src="//user/banners/16/08/1614708.gif" alt="AAA" data-tip="BBB" currentitem="false" class="" width="468" height="60">
I know the id 123456 (part of href)
I tried this xpath that recognize element with a part of href but working in text link only
xpath=//a[contains(#href, "123456")]
How can i detect the element using a part of href only ?
I need xpath only please.
You need get /img in //a where href attribute contains() or ends-with() your id
This is XPATH that you need. At least i would use this XPATH in this situation
//a[ends-with(#href, 'your-id-here')]/img
You can use regular expresions. Something like
driver.find_element_by_xpath("//input[starts-with (#name,'Tut')]")
or as you described
driver.find_element_by_xpath("//input[contains(#name,'sel')]").
Be awere of one thing, do not use double quotes, for the string you are searching as atribute value. Use a single quote like I previously described.
Consider this xpath which should always return one element.
//div[#id='MyDiv123']/div[contains(#class, 'super')]
Assume that we won't add anymore divs whose class is super. Given that info, I don't think that it is a good idea to use /div[contains(#class, 'super')]because the xpath will break if div[contains(#class, 'super')] is placed inside another element.
Shouldn't we be using //div[contains(#class, 'super')] instead ?
I don't like using XPaths for locators that can be written as a CSS selector. I think it's much simpler as
#MyDiv123 > div.super
or just
div.super
if it's unique on the page.
XPath contains() is a string match. All the elements below will match your XPath locator but none of them will match the CSS selectors above.
<div class="super-duper" ...>
<div class="superior" ...>
<div class="abcsuperdef" ...>
... you get the idea...
There is no defined Best Practices while writing xpaths. It all boils down to how effective xpath can be written.
I don't see any issue with the xpath as :
//div[#id='MyDiv123']/div[contains(#class, 'super')]
Of-coarse there ca be some improvements as follows :
As an enduser you won't be sure how the class attribute super impacts the HTML or which elements have this attribute. So in that case to identify the WebElement uniquely it would be wise to include the ancestor <div> tag with id as MyDiv123.
But it doesn't looks like the classname super can be dynamic. Hence you can avoid the keyword contains within the xpath and rewrite it as :
//div[#id='MyDiv123']/div[#class='super']
I have html like
<html>
<body>
<div class='open'>
<h1>Title</h1>
<div>Opened</div>
</div>
</body>
</html>
And in my Selenium WebDriver 3 tests I am trying to select the div.open element using the following xpath:
//h1/../.[contains(#class, 'open')]
In the following command in c#:
driver.FindElement(By.XPath("//h1/../.[contains(#class, 'open')]"));
Which results in
OpenQA.Selenium.InvalidSelectorException : invalid selector:
Unable to locate an element with the xpath expression //h1/../.[contains(#class, 'open')] because of the following error::
Failed to execute 'evaluate' on 'Document': The string '//h1/../.[contains(#class, 'open')]' is not a valid XPath expression.
Searching by the same Xpath in Firefox console successfully locates the element.
Any ideas why WebDriver considers this xpath invalid?
Note: my example is of course simplified
I would say that's probably down to the specification doesn't explicitly state whether predicate after abbreviated step i.e . and .. should be allowed, neither the specification ever mention an example involving predicate after abbreviated step.
So some XPath implementations just don't support it. One of these, I noticed, is XPath implementation in .NET framework. Other implementations explicitly disallow it, and even provide useful suggestion for the user to replace . or .. in their XPath with the equivalent unabbreviated expression, in order, self::node() or parent::node(), for example, the implementation used by xpathtester. But as you noticed, other implementations might support it.
As of workaround, there are many alternatives XPath which equivalent or close enough to you original attempted XPath. The easiest is to expand the . to its unabbreviated expression, as I mentioned above. Personally, I prefer not to go down the tree and then back up to return a parent element, if possible. Instead, just stop at the parent element which we want to return, and check for the child in predicate :
//*[contains(#class, 'open')][h1]
If you want to reference "div" with respect to "h1" tag then you can change the xpath to following:
//h1/ancestor::div[contains(#class, 'open')]
Instead of //h1/../.[contains(#class, 'open')] xpath can you try //div[#class='open'] xpath
I have this code for xpath and html:
<a class="WatchButton inicon" rel="nofollow" data-productid="111124">
xpath=/html/body/div[2]/div[2]/div/div[2]/div[1]/div[1]/div[2]/div[8]/a
How can I get the data-productid value?
Just add #data-productid to the xpath expression:
/html/body/div[2]/div[2]/div/div[2]/div[1]/div[1]/div[2]/div[8]/a/#data-productid
Note that the xpath expression you have is very fragile since it depends on a bunch of elements and their relevant positions. Try to rely on the element's attributes or one of it's containers - look for id and class attributes. For example:
//a[contains(#class, "WatchButton")]/#data-productid
This gets the first link anywhere on a page that contains WatchButton class and retrieves it's data-productid attribute value.
* Sharing the link to the web page or showing the complete HTML could help to provide you with a more reliable xpath expression.