Search code examples
seleniumxpathnestedcontainers

Searching for n-th child in n-th parent


There is a strange behaviour when it comes to finding elements by xpath. The situation:

<body>
...
  <div class="ingredients-group">
    <div class="group-header">
      <h3>Title 1</h3>
      ... other stuff
    </div>
  </div>
  <div class="ingredients-group">
    <div class="group-header">
      <h3>Title 2</h3>
      ... other stuff
    </div>
  </div>
...

I want to check the text of the H3 tag on the second ingredient-group. So I did the following in Selenium:

WebElement group2 = driver.findElement(By.xpath("//div[@class='ingredients-group'][2]"));
WebElement title2 = group2.findElement(By.xpath("//h3"));
String titleText = title2.GetText();  

The last statement returns "Title 1". I would expect it to return "Title 2".

Strangely, this statement returns "Title 2":

String titleText = driver.findElement(By.xpath("//div[@class='ingredients-group'][2]//h3")).getText();

I would like to use the first option (group2.findElement), because there are several other elements in the containers I would like to refer to without having to write the full xpath.

Any ideas on this? Thanks


Solution

  • Use findElements to return a list of webelements (h3 tags) and then access them as you would any other list:

    WebElement groups = driver.findElements(By.xpath("//div[@class='ingredients-group'][2]"));
    WebElement theH3Tag = groups[0].findElement(By.xpath(".//h3")); //make this a relative xpath
    String titleText = theH3Tag.GetText();  
    
    WebElement the2ndH3Tag = groups[1].findElement(By.xpath(".//h3")); //make this a relative xpath
    String titleText = the2ndH3Tag.GetText(); 
    

    Or loop through the list:

        WebElement[] groups = driver.findElements(By.xpath("//div[@class='ingredients-group'][2]"));
        for (WebElement group : groups) {
            WebElement h3Tag = group.findElement(By.xpath(".//h3")); //make this a relative xpath
            String titleText = h3Tag.GetText();
        }