Wybierz element macierzysty znanego elementu w Selenium

116

Mam pewien element, który mogę wybrać z Selenium 1.

Niestety muszę kliknąć element nadrzędny, aby uzyskać żądane zachowanie. Element, który mogę łatwo zlokalizować, ma atrybut niewybieralny, przez co jest martwy po kliknięciu. Jak przejść w górę za pomocą XPath ?

fl
źródło

Odpowiedzi:

169

Jest tam kilka opcji. Przykładowy kod jest napisany w Javie, ale przeniesienie do innych języków powinno być proste.

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

Uzyskanie sterownika z WebElement

Uwaga: jak widać, w przypadku wersji JavaScript potrzebujesz rozszerzenia driver. Jeśli nie masz do niego bezpośredniego dostępu, możesz go odzyskać za WebElementpomocą:

WebDriver driver = ((WrapsDriver) myElement).getWrappedDriver();
acdcjunior
źródło
41
A jeśli chcesz przejść do dziadka, użyj By.Xpath („../ ..”).
Monsignor
@Monsignor Działa tak jak ścieżki do plików ... lub ścieżki URL: stackoverflow.com/questions/8577636/../../questions/8577636/ ...
jpaugh
Żadna z tych ścieżek XPath nie jest odpowiednia do użycia z Selenium. Należy użyć, By.xpath(“./..”)aby poprawnie wejść po drzewie DOM podczas używania element.findElement. Początkowy „./” jest wymagany do ustawienia węzła kontekstu.
JimEvans
35

Trochę więcej o XPath axes

Powiedzmy, że mamy poniższą HTMLstrukturę:

<div class="third_level_ancestor">
    <nav class="second_level_ancestor">
        <div class="parent">
            <span>Child</span>
        </div>
    </nav>
</div>
  1. //span/parent::*- zwraca dowolny element, który jest bezpośrednim rodzicem.

W tym przypadku wyjście to <div class="parent">

  1. //span/parent::div[@class="parent"]- zwraca element rodzica tylko o dokładnym typie węzła i tylko wtedy, gdy określony predykat ma wartość True.

Wynik: <div class="parent">

  1. //span/ancestor::*- zwraca wszystkich przodków (w tym rodzica).

Wyjście: <div class="parent">, <nav class="second_level_ancestor">, <div class="third_level_ancestor">...

  1. //span/ancestor-or-self::*- zwraca wszystkich przodków i sam bieżący element.

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

  1. //span/ancestor::div[2]- zwraca drugiego przodka (zaczynając od rodzica) typu div.

Wynik: <div class="third_level_ancestor">

Andersson
źródło
Witaj @Anderson Potrzebuję pomocy z moim pytaniem Czy masz czas, aby rzucić okiem? Z góry dziękuję. stackoverflow.com/questions/54647055/…
18

Rozważmy Twój DOM jako

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

Teraz, gdy musisz wybrać tag nadrzędny „a” na podstawie <span>tekstu, a następnie użyj

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

Objaśnienie: Wybierz węzeł na podstawie wartości jego węzła potomnego

Bhuvanesh Mani
źródło
Jeśli szukamy, divktóry jest ponownie zagnieżdżony w wielu elementach div, to zamiast .//spanw By.xpath("//div[.//span[text()='Close']]")możemy użyć *//span, będzie szukać większości nadrzędnych elementów div z danego zakresu. Teraz będzie to wyglądać takdriver.findElement(By.xpath("//div[*//span[text()='Close']]"));
Jai Prak
14

Spójrz na możliwe osie XPath , których prawdopodobnie szukaszparent . W zależności od tego, jak znajdujesz pierwszy element, możesz po prostu dostosować do tego ścieżkę xpath.

Alternatywnie możesz wypróbować składnię z podwójną kropką , ..która wybiera rodzica bieżącego węzła.

prestomanifesto
źródło
5

Może to być przydatne dla kogoś innego: używając tego przykładowego kodu 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>

Jeśli na przykład chcę wybrać element w tej samej sekcji (np. Div) jako etykietę, możesz tego użyć

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

Oznacza to tylko, patrzeć na etykiecie (to może coś podobnego a, h2) o nazwie labelName. Przejdź do elementu nadrzędnego tej etykiety (tj div class="ParentDiv".). Przeszukaj elementy potomne tego rodzica, aby znaleźć dowolny element potomny o wartości elementToSelect. Dzięki temu nie wybierze drugiego elementToSelectzDontSelect div jako rodzicem.

Sztuczka polega na tym, że możesz zmniejszyć obszary wyszukiwania dla elementu, przechodząc najpierw do elementu nadrzędnego, a następnie wyszukując element potomny tego elementu nadrzędnego, którego potrzebujesz. following-sibling::h2W niektórych przypadkach można również użyć innej składni, takiej jak . Oznacza to następny element rodzeństwa h2. To zadziała dla elementów na tym samym poziomie, mających tego samego rodzica.

papigee
źródło
0

Możesz to zrobić używając / parent :: node () w xpath. Po prostu dołącz / parent :: node () do elementów potomnych xpath.

Na przykład: Niech xpath elementu potomnego to childElementXpath .

Wtedy xpath jego bezpośredniego przodka byłby childElementXpath / parent :: node () .

Xpath jego następnego przodka to childElementXpath / parent :: node () / parent :: node ()

i tak dalej..

Możesz również przejść do przodka elementu za pomocą 'childElementXpath/ancestor::*[@attr="attr_value"]'. Byłoby to przydatne, gdy masz znany element potomny, który jest unikalny, ale ma element nadrzędny, którego nie można jednoznacznie zidentyfikować.

Johnes Jose
źródło
0

Za pomocą Selenium możemy wybrać tag nadrzędny w następujący sposób:

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

pomoże ci to znaleźć dziadka znanego elementu. Po prostu usuń jeden (/ ..), aby znaleźć bezpośredni element nadrzędny.

Lubić:

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

Jest kilka innych sposobów, aby to zaimplementować, ale dla mnie zadziałało dobrze.

Utsav Jain
źródło