Выберите родительский элемент известного элемента в Selenium


116

У меня есть определенный элемент, который я могу выбрать с помощью Selenium 1.

К сожалению, мне нужно щелкнуть родительский элемент, чтобы получить желаемое поведение. Элемент, который я могу легко найти, имеет атрибут unselectable, что делает его мертвым для щелчка. Как с помощью XPath перемещаться вверх ?

Ответы:


169

Там есть пара вариантов. Пример кода написан на Java, но перенос на другие языки должен быть простым.

JavaScript:

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("./.."));

Получение драйвера из WebElement

Примечание. Как видите, для версии JavaScript вам понадобится расширение driver. Если у вас нет прямого доступа к нему, вы можете получить его с WebElementпомощью:

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

41
А если вы хотите перейти к дедушке и бабушке, используйте By.Xpath ("../ ..").
Monsignor

@Monsignor Работает так же, как пути к файлам ... или пути URL: stackoverflow.com/questions/8577636/../../questions/8577636/…
jpaugh

Ни один из этих XPath не подходит для использования с Selenium. Нужно использовать, By.xpath(“./..”)чтобы правильно пройти по дереву DOM при использовании element.findElement. Ведущий «./» требуется для установки контекстного узла.
JimEvans 08

35

Еще немного о XPath axes

Допустим, у нас есть HTMLструктура ниже :

<div class="third_level_ancestor">
    <nav class="second_level_ancestor">
        <div class="parent">
            <span>Child</span>
        </div>
    </nav>
</div>
  1. //span/parent::*- возвращает любой элемент, являющийся прямым родителем.

В этом случае вывод <div class="parent">

  1. //span/parent::div[@class="parent"]- возвращает родительский элемент только точного типа узла и только если указанный предикат истинен.

Вывод: <div class="parent">

  1. //span/ancestor::*- возвращает всех предков (включая родителя).

Выход: <div class="parent">, <nav class="second_level_ancestor">, <div class="third_level_ancestor">...

  1. //span/ancestor-or-self::*- возвращает все предков и сам текущий элемент.

Выход: <span>Child</span>,<div class="parent"> , <nav class="second_level_ancestor">, <div class="third_level_ancestor">...

  1. //span/ancestor::div[2]- возвращает второго предка (начиная с родительского) типа div.

Вывод: <div class="third_level_ancestor">


Привет, @Anderson. Мне нужна помощь с вопросом. У тебя есть время взглянуть? Заранее спасибо. stackoverflow.com/questions/54647055/…

18

Рассмотрим вашу DOM как

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

Теперь, когда вам нужно выбрать родительский тег 'a' на основе <span>текста, используйте

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

Объяснение: Выберите узел на основе значения его дочернего узла.


Если мы ищем , divкоторый снова вложенный с несколькими дивами , то вместо того , чтобы .//spanв By.xpath("//div[.//span[text()='Close']]")мы можем использовать *//span, это будет выглядеть для большинства родительского сНу элемента данного диапазона. Теперь это будет выглядеть такdriver.findElement(By.xpath("//div[*//span[text()='Close']]"));
Jai Prak

14

Взгляните на возможные оси XPath , которые вы, вероятно, ищете parent. В зависимости от того, как вы находите первый элемент, вы можете просто настроить для него xpath.

В качестве альтернативы вы можете попробовать синтаксис с двумя точками , ..который выбирает родительский элемент текущего узла.


5

Это может быть полезно для кого-то еще: Использование этого образца 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>

Если, например, я хочу выбрать элемент в том же разделе (например, div) в качестве метки, вы можете использовать это

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

Это просто означает, обратите внимание на этикетку (он мог что - нибудь подобное a, h2) называется labelName. Перейдите к родительскому элементу этой метки (т.е. div class="ParentDiv"). Выполните поиск среди потомков этого родителя, чтобы найти любой дочерний элемент со значением elementToSelect. При этом он не будет выбирать второй elementToSelectсDontSelect div в качестве родителя.

Хитрость заключается в том, что вы можете уменьшить области поиска для элемента, сначала перейдя к родительскому элементу, а затем выполнив поиск в потомке этого родителя для нужного вам элемента. В following-sibling::h2некоторых случаях также можно использовать другой синтаксис . Это означает, что за элементом следует элемент h2. Это будет работать для элементов на одном уровне, имеющих одного и того же родителя.


0

Вы можете сделать это, используя / parent :: node () в xpath. Просто добавьте / parent :: node () к дочерним элементам xpath.

Например: пусть xpath дочернего элемента - childElementXpath .

Тогда xpath его непосредственного предка будет childElementXpath / parent :: node () .

Xpath его следующего предка будет childElementXpath / parent :: node () / parent :: node ()

и так далее..

Кроме того, вы можете перейти к предку элемента с помощью 'childElementXpath/ancestor::*[@attr="attr_value"]'. Это было бы полезно, когда у вас есть известный дочерний элемент, который уникален, но имеет родительский элемент, который нельзя однозначно идентифицировать.


0

Мы можем выбрать родительский тег с помощью Selenium следующим образом:

driver.findElement(By.xpath("//table[@id='abc']//div/nobr[.='abc']/../.."));

это поможет вам найти прародителя известного элемента. Просто удалите один (/ ..), чтобы найти непосредственный родительский элемент.

Подобно:

driver.findElement(By.xpath("//table[@id='abc']//div/nobr[.='abc']/..));

Есть и другие способы реализовать это, но у меня это сработало.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.