Selenium XPath - how to find immediately preceding element

10,913

You can get required result by specifying the index:

./preceding-sibling::input[1]

In this case you'll get the first (immediate) preceding-sibling of type "input"

Share:
10,913
mckrecker
Author by

mckrecker

Updated on June 04, 2022

Comments

  • mckrecker
    mckrecker about 2 years

    I am running tests in Java Selenium where I find an element, and once found need to find the immediately preceding element. The code needs to be dynamic because I don't know if the element I start from is the 3rd out of 5, the 6th out of 10, or the 1st out of 2.

    The problem is, using preceding-sibling from xpath, I get all elements preceding the found element, not the one immediately preceding it. For example, this is my xml:

    <div>
        <input formcontrolname="myValues" id="value1" type="radio" value="VALUE1" />
        <label for="value1">Value 1</label>
        <input formcontrolname="myValues" id="value2" type="radio" value="VALUE2" />
        <label for="value2">Value 2</label>
    </div>
    

    Lets say I have found the 'Value 2' label as a WebElement, then I want to do next is find the specific input immediately preceding that label (id='value2'). Since it has to be relative to the label I've found, I can't just find by that id; I don't really know the id, just that the input is supposed to precede the label. I thought I could use this:

    WebElement input = element.findElement(By.xpath("preceding-sibling::input"));
    

    But that xpath actually returns all the inputs that are siblings of the label. So, in the example, I get an array of two inputs returned, both 'value1' and 'value2'. Selenium sets the value of input to be the input with id='value1', the first in the returned array.

    So my question is, is there an xpath that will return the one element that immediately precedes a given element?

  • mckrecker
    mckrecker over 6 years
    Yeah, that's the issue though -- i don't actually know in the app I'm testing what the input's id attribute is. All I know is that it immediately precedes the label.
  • mckrecker
    mckrecker over 6 years
    The problem is I don't know the index. What if there are three sets of labels and inputs, instead of 2? I can't be sure of the index.
  • mckrecker
    mckrecker over 6 years
    What I do is fine the label as a WebElement, then I find the input based on that element. So it's not driver.findElement(), it's myElement.findElement(). so, if I did it in a single statement (using Java) it would look like: driver.findElement(By.xpath("//label[@for='value1'").findEle‌​ment(By.xpath("prece‌​ding-sibling::input"‌​);
  • Andersson
    Andersson over 6 years
    No. This is not the absolute index of element, this is the relative index and it just means "the closest input sibling to current node". Even if there are thousands of sets - this XPath will match the first sibling
  • mckrecker
    mckrecker over 6 years
    Got it. Works perfectly. Thanks. You can it here with more than 2 elements: xpathtester.com/xpath/e6ec6df0e2f5930d44c9c3ece00fc59c xpath = //label[@for='value4']/preceding-sibling::input[1]
  • mckrecker
    mckrecker over 6 years
    see chosen answer -- basically the same as this.
  • undetected Selenium
    undetected Selenium over 6 years
    Check out my updated Answer and let me know your thoughts.
  • Andersson
    Andersson over 6 years
    @DebanjanB , interesting thought :) So you want to say that using preceding-sibling doesn't suit much the case when OP wants to get preceding-sibling ? ))) preceding-sibling/following-sibling should be used exactly for these cases while previous/following - for cases when you want to get nodes on different DOM levels!