Select parent element of known element in Selenium

218,899

Solution 1

There are a couple of options there. The sample code is in Java, but a port to other languages should be straightforward.

Java:

WebElement myElement = driver.findElement(By.id("myDiv"));
WebElement parent = (WebElement) ((JavascriptExecutor) driver).executeScript(
                                   "return arguments[0].parentNode;", myElement);

XPath:

WebElement myElement = driver.findElement(By.id("myDiv"));
WebElement parent = myElement.findElement(By.xpath("./.."));

Obtaining the driver from the WebElement

Note: As you can see, for the JavaScript version you'll need the driver. If you don't have direct access to it, you can retrieve it from the WebElement using:

WebDriver driver = ((WrapsDriver) myElement).getWrappedDriver();

Solution 2

Little more about XPath axes

Lets say we have below HTML structure:

<div class="third_level_ancestor">
    <nav class="second_level_ancestor">
        <div class="parent">
            <span>Child</span>
        </div>
    </nav>
</div>
  1. //span/parent::* - returns any element which is direct parent.

In this case output is <div class="parent">

  1. //span/parent::div[@class="parent"] - returns parent element only of exact node type and only if specified predicate is True.

Output: <div class="parent">

  1. //span/ancestor::* - returns all ancestors (including parent).

Output: <div class="parent">, <nav class="second_level_ancestor">, <div class="third_level_ancestor">...

  1. //span/ancestor-or-self::* - returns all ancestors and current element itself.

Output: <span>Child</span>, <div class="parent">, <nav class="second_level_ancestor">, <div class="third_level_ancestor">...

  1. //span/ancestor::div[2] - returns second ancestor (starting from parent) of type div.

Output: <div class="third_level_ancestor">

Solution 3

Let's consider your DOM as

<a>
    <!-- some other icons and texts -->
    <span>Close</span>
</a>

Now that you need to select parent tag 'a' based on <span> text, then use

driver.findElement(By.xpath("//a[.//span[text()='Close']]"));

Explanation: Select the node based on its child node's value

Solution 4

Take a look at the possible XPath axes, you are probably looking for parent. Depending on how you are finding the first element, you could just adjust the xpath for that.

Alternatively you can try the double-dot syntax, .. which selects the parent of the current node.

Solution 5

This might be useful for someone else: Using this sample html

<div class="ParentDiv">
    <label for="label">labelName</label>
    <input type="button" value="elementToSelect">
</div>
<div class="DontSelect">
    <label for="animal">pig</label>
    <input type="button" value="elementToSelect">
</div>

If for example, I want to select an element in the same section (e.g div) as a label, you can use this

//label[contains(., 'labelName')]/parent::*//input[@value='elementToSelect'] 

This just means, look for a label (it could anything like a, h2) called labelName. Navigate to the parent of that label (i.e. div class="ParentDiv"). Search within the descendants of that parent to find any child element with the value of elementToSelect. With this, it will not select the second elementToSelect with DontSelect div as parent.

The trick is that you can reduce search areas for an element by navigating to the parent first and then searching descendant of that parent for the element you need. Other Syntax like following-sibling::h2 can also be used in some cases. This means the sibling following element h2. This will work for elements at the same level, having the same parent.

Share:
218,899
f l
Author by

f l

Updated on October 29, 2020

Comments

  • f l
    f l over 3 years

    I have a certain element that I can select with Selenium 1.

    Unfortunately I need to click the parent element to get the desired behaviour. The element I can easily locate has attribute unselectable, making it dead for clicking. How do I navigate upwards with XPath?

  • Monsignor
    Monsignor over 10 years
    And if you want to navigate to the grandparent, use By.Xpath("../..").
  • jpaugh
    jpaugh over 6 years
    @Monsignor Works just like file paths... or URL paths: stackoverflow.com/questions/8577636/../../questions/8577636/‌​…
  • Jai Prak
    Jai Prak almost 6 years
    If we are looking for div which is again nested with multiple divs then instead of .//span in By.xpath("//div[.//span[text()='Close']]") we can use *//span, it will look for most parent div element of given span. Now it will look like this driver.findElement(By.xpath("//div[*//span[text()='Close']]"‌​));
  • JimEvans
    JimEvans over 5 years
    None of these XPaths are correct for use with Selenium. One needs to use By.xpath(“./..”) to correctly walk up the DOM tree when using element.findElement. The leading “./“ is required to set the context node.
  • Admin
    Admin about 5 years
    Hello @Anderson I need help with my question Do you have time to take a look? Thank you in advance. stackoverflow.com/questions/54647055/…
  • Ashark
    Ashark about 2 years
    For selenium 4: driver.find_element(By.XPATH, "//button[.//span[text()='Close']]")
  • Pete Kelley
    Pete Kelley almost 2 years
    I prefer your answer due to its simplicity and clarity. I appreciate how you have summed up the solution that seemed to be asked for. I did vote up the accepted answer too-because that was helpful for reasons other than the original question.