Seleccione el elemento principal del elemento conocido en Selenium

116

Tengo un determinado elemento que puedo seleccionar con Selenium 1.

Desafortunadamente, necesito hacer clic en el elemento principal para obtener el comportamiento deseado. El elemento que puedo localizar fácilmente tiene un atributo no seleccionable, lo que lo hace inactivo para hacer clic. ¿Cómo navego hacia arriba con XPath ?

Florida
fuente

Respuestas:

169

Hay un par de opciones ahí. El código de muestra está en Java, pero la adaptación a otros lenguajes debería ser sencilla.

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

Obtener el controlador del WebElement

Nota: Como puede ver, para la versión de JavaScript necesitará driver. Si no tiene acceso directo a él, puede recuperarlo WebElementusando:

WebDriver driver = ((WrapsDriver) myElement).getWrappedDriver();
acdcjunior
fuente
41
Y si desea navegar hasta el abuelo, use By.Xpath ("../ ..").
Monseñor
@Monsignor funciona como rutas de archivo ... o rutas de URL: stackoverflow.com/questions/8577636/../../questions/8577636/…
jpaugh
Ninguno de estos XPaths es correcto para su uso con Selenium. Se necesita usar By.xpath(“./..”)para subir correctamente el árbol DOM cuando se usa element.findElement. El "./" inicial es necesario para establecer el nodo de contexto.
JimEvans
35

Poco más sobre XPath axes

Digamos que tenemos la siguiente HTMLestructura:

<div class="third_level_ancestor">
    <nav class="second_level_ancestor">
        <div class="parent">
            <span>Child</span>
        </div>
    </nav>
</div>
  1. //span/parent::*- devuelve cualquier elemento que sea padre directo.

En este caso la salida es <div class="parent">

  1. //span/parent::div[@class="parent"]- devuelve el elemento padre solo del tipo de nodo exacto y solo si el predicado especificado es Verdadero.

Salida: <div class="parent">

  1. //span/ancestor::*- devuelve todos los antepasados ​​(incluido el padre).

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

  1. //span/ancestor-or-self::*- devuelve todos los antepasados y el elemento actual en sí.

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

  1. //span/ancestor::div[2]- devuelve el segundo ancestro (comenzando por el padre) de tipo div.

Salida: <div class="third_level_ancestor">

Andersson
fuente
Hola @Anderson Necesito ayuda con mi pregunta ¿Tienes tiempo para echar un vistazo? Gracias de antemano. stackoverflow.com/questions/54647055/…
18

Consideremos su DOM como

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

Ahora que necesita seleccionar la etiqueta principal 'a' según el <span>texto, utilice

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

Explicación: seleccione el nodo según el valor de su nodo secundario

Bhuvanesh Mani
fuente
Si estamos buscando divque está anidado de nuevo con varias Div entonces en vez de .//spanen By.xpath("//div[.//span[text()='Close']]")que podemos utilizar *//span, que se verá durante la mayor parte de los padres elemento div del rango dado. Ahora se verá asídriver.findElement(By.xpath("//div[*//span[text()='Close']]"));
Jai Prak
14

Eche un vistazo a los posibles ejes XPath que probablemente esté buscando parent. Dependiendo de cómo encuentre el primer elemento, puede ajustar el xpath para eso.

Alternativamente, puede probar la sintaxis de doble punto , ..que selecciona el padre del nodo actual.

prestomanifesto
fuente
5

Esto podría ser útil para otra persona: Usar este HTML de muestra

<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>

Si, por ejemplo, quiero seleccionar un elemento en la misma sección (por ejemplo, div) como etiqueta, puede usar esto

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

Esto sólo significa, busque una etiqueta (Podría algo así a, h2) llamado labelName. Navegue hasta el padre de esa etiqueta (es decir div class="ParentDiv"). Busque dentro de los descendientes de ese padre para encontrar cualquier elemento hijo con el valor de elementToSelect. Con esto, no seleccionará el segundo elementToSelectcon DontSelectdiv como padre.

El truco es que puede reducir las áreas de búsqueda de un elemento navegando primero al padre y luego buscando el elemento que necesita en el descendiente de ese padre. following-sibling::h2En algunos casos también se pueden utilizar otras sintaxis similares . Esto significa el elemento siguiente del hermano h2. Esto funcionará para elementos del mismo nivel, que tengan el mismo padre.

papigee
fuente
0

Puede hacer esto usando / parent :: node () en el xpath. Simplemente agregue / parent :: node () a los elementos secundarios xpath.

Por ejemplo: Sea xpath del elemento hijo childElementXpath .

Entonces xpath de su antepasado inmediato sería childElementXpath / parent :: node () .

XPath de su próximo antepasado sería childElementXpath / parent :: node () / parent :: node ()

y así..

Además, puede navegar a un ancestro de un elemento usando 'childElementXpath/ancestor::*[@attr="attr_value"]'. Esto sería útil cuando tiene un elemento hijo conocido que es único pero tiene un elemento padre que no se puede identificar de forma única.

Johnes José
fuente
0

Podemos seleccionar la etiqueta principal con la ayuda de Selenium de la siguiente manera:

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

esto te ayudará a encontrar al abuelo del Elemento conocido. Simplemente elimine uno (/ ..) para encontrar el elemento principal inmediato.

Me gusta:

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

Hay otras formas de implementar esto, pero funcionó bien para mí.

Utsav Jain
fuente