Selenium XPath - how to find immediately preceding element
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"
![mckrecker](https://i.stack.imgur.com/pnXpX.jpg?s=256&g=1)
mckrecker
Updated on June 04, 2022Comments
-
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 over 6 yearsYeah, 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 over 6 yearsThe 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 over 6 yearsWhat 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'smyElement.findElement()
. so, if I did it in a single statement (using Java) it would look like:driver.findElement(By.xpath("//label[@for='value1'").findElement(By.xpath("preceding-sibling::input");
-
Andersson over 6 yearsNo. 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 over 6 yearsGot 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 over 6 yearssee chosen answer -- basically the same as this.
-
undetected Selenium over 6 yearsCheck out my updated Answer and let me know your thoughts.
-
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 whileprevious
/following
- for cases when you want to get nodes on different DOM levels!