[SOLVED] Distinguishing between the same web elements with Python Selenium based on relates

Issue

This Content is from Stack Overflow. Question asked by Sparky13

After third attempt of solving this problem, I am unable to finalize this on my own. I would appreciate, if someone would like to share their thoughts on the following issue.

Let us assume, we have such kind of HTML structure:

<div class="panel"></div>
    <div class="title"></div>
        <h3 class="title">HEADER NUMBER ONE<h3>
    <div class="area"></div>
        <div class="something">IO field</div>
            <input class="input"></input>
            
<div class="panel"></div>
    <div class="title"></div>
        <h3 class="title">HEADER NUMBER TWO<h3>
    <div class="area"></div>
        <div class="something">IO field</div>
            <input class="input"></input>

My intention is to identify an input element that belongs to the second panel.

Based on reliability check, when I have hardcoded XPATH gathered directly from the browser, sometimes wrong element is being identified (I assume that there are many scripts running when the page is being loaded, which impacts the reliability and stability). Therefore I would like to distinguish between elements based on the h3, which are the one and only difference between objects.

How can I do it?

When identifying elements one by one (so first the title, then its parent, and then moving down to the input), I receive an “element not interactable” exception which is not dependent from the time.

I am thinking of something like:

find //input[@class='input'] where one of ancestors contains /div/h3 which contains(text(), 'HEADER NUMBER TWO')

Obviously, I did not found any working solution for that, despite I spent more than a week with that.

Is it doable at all? If so, could you suggest me something, please? The structure in real is a little bit more complex, but I need just a pattern, hint, or clue.

Greetings!



Solution

You can locate the parent panel element based on it’s child h3 with the desired title and then to locate the input element inside it.
The XPath to do so can look like the following:

"//div[@class='panel' and(.//h3[contains(.,'HEADER NUMBER ONE')])]//input"

Or even

"//div[@class='panel' and(contains(.,'HEADER NUMBER ONE'))]//input"

The selenium command using that XPath can look like:

driver.find_element(By.XPATH, "//div[@class='panel' and(contains(.,'HEADER NUMBER ONE'))]//input")

More explanations
The XPath

"//div[@class='panel' and(.//h3[contains(.,'HEADER NUMBER ONE')])]//input"

literally means:
Find element with div tag and class attribute value panel and having some child element inside it (this is .// comes for) containing HEADER NUMBER ONE text content.
Inside the above div element find input child element.


This Question was asked in StackOverflow by Sparky13 and Answered by Prophet It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?