Dealing with duplicate ids in selenium webdriver

16,774

Solution 1

you can do it by driver.find_element_by_id, for example ur duplicate "duplicate_ID" is inside "div_ID" wich is unique :

driver.find_element_by_id("div_ID").find_element_by_id("duplicate_id")

for other duplicate id under another div :

driver.find_element_by_id("div_ID2").find_element_by_id("duplicate_id")

Solution 2

This XPath expression:

//div[@id='something']

selects all div elements in the XML document, the string value of whose id attribute is the string "something".

This Xpath expression:

count(//div[@id='something'])

produces the number of the div elements selected by the first XPath expression.

And this XPath expression:

(//div[@id='something'])[3]

selects the third (in document order) div element that is selected by the first XPath expression above.

Generally:

(//div[@id='something'])[$k]

selects the $k-th such div element ($k must be substituted with a positive integer).

Equipped with this knowledge, one can get any specific div whose id attribute has string value "something".

Solution 3

Which language are you working on? Dublicate id's shouldn't be a problem as you can virtually grab any attribute not just the id tag using xpath. The syntax will differ slightly in other languages (let me know if you want something else than Ruby) but this is how you do it:

driver.find_element(:xpath, "//input[@id='loginid']"

The way you go about constructing the xpath locator is the following: From the html code you can pick any attribute:

<input id="gbqfq" class="gbqfif" type="text" value="" autocomplete="off" name="q">

Let's say for example that you want to consturct your xpath with the html code above (Google's search box) using name attribute. Your xpath will be:

    driver.find_element(:xpath, "//input[@name='q']"

In other words when the id's are the same just grab another attribute available!

Improvement:

To avoid fragile xpath locators such as order in the XML document (which can change easily) you can use something even more robust. Two xpath locators instead of one. This can also be useful when dealing with hmtl tags that are really similar. You can locate an element by 2 of its attributes like this:

driver.find_element(:id, 'amount') and driver.find_element(xpath: "//input[@maxlength='50']")

or in pure xpath one liner if you prefer:

//input[@id="amount" and @maxlength='50']

Alternatively (and provided your xpath will only return one unique element) you can move one more step higher in the abstraction level; completely omitting the attribute values:

//input[@id and @maxlength]

Solution 4

It's not listed at http://selenium-python.readthedocs.io/locating-elements.html but I'm able access a method find_elements_by_id

This returns a list of all elements with the duplicate ID.

links = browser.find_elements_by_id("link")
for link in links:
    print(link.get_attribute("href"))
Share:
16,774
ftrotter
Author by

ftrotter

php is showing its age, learning node. Node is frustrating. Learning python.

Updated on June 13, 2022

Comments

  • ftrotter
    ftrotter about 2 years

    I am trying to automate some tests using selenium webdriver. I am dealing with a third-party login provider (OAuth) who is using duplicate id's in their html. As a result I cannot "find" the input fields correctly. When I just select on an id, I get the wrong one.

    This question has already been answered for JQuery. But I would like an answer (I am presuming using Xpath) that will work in Selenium webdriver.

    On other questions about this issue, answers typically say "you should not have duplicate id's in html". Preaching to the choir there. I am not in control of the webpage in question. If it was, I would use class and id properly and just fix the problem that way.

    Since I cannot do that. What options do I get with xpath etc?

  • AussieJoe
    AussieJoe about 6 years
    I never realized you could do this. Amazing!