Selecione o elemento pai do elemento conhecido no Selênio

116

Tenho um certo elemento que posso selecionar com Selenium 1.

Infelizmente, preciso clicar no elemento pai para obter o comportamento desejado. O elemento que posso localizar facilmente tem um atributo não selecionável, tornando-o morto para cliques. Como faço para navegar para cima com o XPath ?

fl
fonte

Respostas:

169

Existem algumas opções lá. O código de amostra está em Java, mas uma porta para outras linguagens deve ser direta.

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

Obtendo o driver do WebElement

Nota: Como você pode ver, para a versão JavaScript você precisará do driver. Se você não tiver acesso direto a ele, pode recuperá-lo WebElementusando:

WebDriver driver = ((WrapsDriver) myElement).getWrappedDriver();
acdcjunior
fonte
41
E se você quiser navegar até o avô, use By.Xpath ("../ ..").
Monsenhor
@Monsignor Funciona como caminhos de arquivo ... ou caminhos de URL: stackoverflow.com/questions/8577636/../../questions/8577636/…
jpaugh
Nenhum desses XPaths é correto para uso com Selenium. É necessário usar By.xpath(“./..”)para subir corretamente a árvore DOM ao usar element.findElement. O primeiro “./“ é necessário para definir o nó de contexto.
JimEvans
35

Um pouco mais sobre XPath axes

Digamos que temos a HTMLestrutura abaixo :

<div class="third_level_ancestor">
    <nav class="second_level_ancestor">
        <div class="parent">
            <span>Child</span>
        </div>
    </nav>
</div>
  1. //span/parent::*- retorna qualquer elemento que seja pai direto.

Neste caso, a saída é <div class="parent">

  1. //span/parent::div[@class="parent"]- retorna o elemento pai apenas do tipo de nó exato e apenas se o predicado especificado for True.

Resultado: <div class="parent">

  1. //span/ancestor::*- retorna todos os ancestrais (incluindo o pai).

Saída: <div class="parent">, <nav class="second_level_ancestor">, <div class="third_level_ancestor">...

  1. //span/ancestor-or-self::*- retorna todos os ancestrais e o próprio elemento atual.

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

  1. //span/ancestor::div[2]- retorna o segundo ancestral (começando do pai) do tipo div.

Resultado: <div class="third_level_ancestor">

Andersson
fonte
Olá @Anderson, preciso de ajuda com minha dúvida. Você tem tempo para dar uma olhada? Agradeço antecipadamente. stackoverflow.com/questions/54647055/…
18

Vamos considerar o seu DOM como

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

Agora que você precisa selecionar a tag pai 'a' com base no <span>texto, use

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

Explicação: Selecione o nó com base no valor de seu nó filho

Bhuvanesh Mani
fonte
Se estivermos procurando por divqual está novamente aninhado com vários divs, então, em vez de .//spanin By.xpath("//div[.//span[text()='Close']]"), podemos usar *//span, ele irá procurar a maioria dos elementos div pai de determinado período. Agora será parecido com istodriver.findElement(By.xpath("//div[*//span[text()='Close']]"));
Jai Prak
14

Dê uma olhada nos possíveis eixos XPath que você provavelmente está procurando parent. Dependendo de como você está encontrando o primeiro elemento, você pode apenas ajustar o xpath para isso.

Como alternativa, você pode tentar a sintaxe de ponto duplo , ..que seleciona o pai do nó atual.

prestomanifesto
fonte
5

Isso pode ser útil para outra pessoa: Usando este exemplo de 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>

Se, por exemplo, eu quiser selecionar um elemento na mesma seção (por exemplo, div) como um rótulo, você pode usar este

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

Isso significa apenas, procure um rótulo (poderia ser qualquer coisa como a, h2) chamado labelName. Navegue até o pai dessa etiqueta (ou seja div class="ParentDiv"). Pesquise nos descendentes desse pai para encontrar qualquer elemento filho com o valor de elementToSelect. Com isso, ele não selecionará o segundo elementToSelectcom DontSelectdiv como pai.

O truque é que você pode reduzir as áreas de pesquisa de um elemento navegando até o pai primeiro e, em seguida, pesquisando no descendente desse pai o elemento de que você precisa. Outra sintaxe semelhante following-sibling::h2também pode ser usada em alguns casos. Isso significa o elemento irmão seguinte h2. Isso funcionará para elementos no mesmo nível, tendo o mesmo pai.

papigee
fonte
0

Você pode fazer isso usando / parent :: node () no xpath. Simplesmente anexe / parent :: node () aos elementos filhos xpath.

Por exemplo: Deixe xpath do elemento filho ser childElementXpath .

Então xpath de seu ancestral imediato seria childElementXpath / parent :: node () .

Xpath de seu próximo ancestral seria childElementXpath / parent :: node () / parent :: node ()

e assim por diante..

Além disso, você pode navegar até um ancestral de um elemento usando 'childElementXpath/ancestor::*[@attr="attr_value"]'. Isso seria útil quando você tiver um elemento filho conhecido que é único, mas possui um elemento pai que não pode ser identificado exclusivamente.

Johnes jose
fonte
0

Podemos selecionar a tag pai com a ajuda do Selenium da seguinte maneira:

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

isso o ajudará a encontrar o avô do elemento conhecido. Basta remover um (/ ..) para encontrar o elemento pai imediato.

Gostar:

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

Existem algumas outras maneiras de implementar isso, mas funcionou bem para mim.

Utsav Jain
fonte