¿Cómo puedo encontrar un elemento por clase CSS con XPath?

Respuestas:

472

Este selector debería funcionar, pero será más eficiente si lo reemplaza con su marcado adecuado:

//*[contains(@class, 'Test')]

O, como sabemos, el elemento buscado es un div:

//div[contains(@class, 'Test')]

Pero como esto también coincidirá con casos como class="Testvalue"o class="newTest", la versión de @ Tomalak proporcionada en los comentarios es mejor :

//div[contains(concat(' ', @class, ' '), ' Test ')]

Si desea estar realmente seguro de que coincidirá correctamente, también puede usar la función normalizar-espacio para limpiar los caracteres de espacio en blanco alrededor del nombre de la clase (como lo menciona @Terry):

//div[contains(concat(' ', normalize-space(@class), ' '), ' Test ')]

Tenga en cuenta que en todas estas versiones, el * debe reemplazarse mejor por cualquier nombre de elemento que realmente desee que coincida, a menos que desee buscar en cada elemento del documento la condición dada.

meder omuraliev
fuente
37
@meder: Más bien //div[contains(concat(' ', @class, ' '), ' Test ')]: el tuyo también mostrará coincidencias parciales.
Tomalak
55
¿Por qué no haces // div [@ class = 'Test']
Jessica
11
Porque las clases pueden contener más de un valor
meder omuraliev
8
Me sorprende que xpath no tenga un acceso directo / una forma más eficiente de ubicar un token en una lista de tokens separados por espacios. ¿Algo en versiones posteriores de xpath?
thomasrutter
1
@thomasrutter por qué la sorpresa: este es solo un lenguaje hecho para XML, no el HTML más específico, y quién puede decir que es casual usar listas separadas por espacios como cualquier valor de nodo en XML. La solución de Tomalak es muy viable.
bitooleano
152

La forma más fácil ...

//div[@class="Test"]

Suponiendo que desea encontrar <div class="Test">como se describe.

Olli Puljula
fuente
3
La sintaxis anterior es mucho más fácil de usar y es menos propensa a errores. RECUERDE que necesita tener las COTIZACIONES DOBLES alrededor de la clase para buscar. Recomendaría usar lo mencionado anteriormente. // div [@ class = "Test"]
FlyingV
¿Funciona esto para los casos en que div [class = 'Test'] se encuentra en un nivel más profundo?
Jake0x32
1
@ Jake0x32, eso se debe a que //no solo usa /.
Solomon Ucko
77
¿Coincide con `<div class =" Test some-other-class "> también?
Jugal Thakkar
11
@JugalThakkar No, no lo hace. Requiere una coincidencia exacta para funcionar, pero puede intentar // div [contiene (@clase, "Prueba")] en su lugar.
Olli Puljula
29

La ÚNICA forma correcta de hacerlo con XPath:

//div[contains(concat(" ", normalize-space(@class), " "), " Test ")]

La función normalize-spaceelimina los espacios en blanco iniciales y finales, y también reemplaza las secuencias de caracteres de espacios en blanco por un solo espacio.


Nota

Si no necesita muchas de estas consultas Xpath, es posible que desee utilizar una biblioteca que convierta los selectores CSS a XPath, ya que los selectores CSS suelen ser mucho más fáciles de leer y escribir que las consultas XPath. Por ejemplo, en este caso, podría usar ambos div[class~="Test"]y div.Testobtener el mismo resultado.

Algunas bibliotecas que he podido encontrar:

John Slegers
fuente
24

Solo estoy proporcionando esto como respuesta, como Tomalak proporcionó como un comentario a la respuesta de Meder hace mucho tiempo

//div[contains(concat(' ', @class, ' '), ' Test ')]
Alex Lyman
fuente
3
Lamento mencionar esto desde hace tanto tiempo, pero ¿qué hay concat(' ', normalize-space(@class), ' ')de tener en cuenta todo tipo de caracteres de espacio en blanco también?
Terry
Por curiosidad, ¿por qué //div[contains(concat(' ', @class, ' '), ' Test ')]/chidno selecciona niños?
Fusion
@Fusion si publica eso como una pregunta, puede obtener una respuesta.
bitooleano
@bitoolean ser Capitán Cbvious es difícil en estos días
Fusion
@ Fusion Solo estaba tratando de ayudar. XPath no es un lenguaje compatible con HTML. Es más genérico, solo XML. No tengo ninguna experiencia en ello, pero creo que estás asumiendo que puedes poner la identificación en lugar de la etiqueta. Debe seleccionar el valor del atributo "id". Por lo tanto, debe pensar en el documento HTML como XML. Sin embargo, las discusiones fuera del tema no ayudan a las personas a encontrar soluciones.
bitooleano
1

Se puede hacer una función útil a partir de respuestas anteriores:

function matchClass($className) {
    return "[contains(concat(' ', normalize-space(@class), ' '), ' $className ')]";
}

Luego simplemente concat la llamada a la función en su consulta.

Carcigenicate
fuente
Ese código solo funcionaría en PHP. Podrías haberlo mencionado.
bitooleano
0

Empareja contra una clase que tenga espacios en blanco.

<div class="hello "></div>
//div[normalize-space(@class)="hello"]
Philip
fuente
-6

puedes encontrar elementos como este ejemplo (todos los elementos css)

private By 
allElementsCss = By.xpath(".//div[@class]");
Sergei Zhilinski
fuente