Comment puis-je trouver un élément par classe CSS avec XPath?

297

Dans ma page Web, il y a un divavec un classnom Test.

Comment puis-je le trouver avec XPath?

fraise
la source
Les solutions XPath, CSS, DOM et Selenium plus générales sont disponibles dans le document XPath, CSS, DOM et Selenium: The Rosetta Stone . Plus précisément, votre réponse se trouve dans l'élément Identifiant et nom .
Terence Xie

Réponses:

473

Ce sélecteur devrait fonctionner mais sera plus efficace si vous le remplacez par votre balisage adapté:

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

Ou, puisque nous savons que l'élément recherché est un div:

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

Mais comme cela correspondra également à des cas comme class="Testvalue"ou class="newTest", la version de @ Tomalak fournie dans les commentaires est meilleure :

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

Si vous souhaitez être vraiment certain qu'il correspondra correctement, vous pouvez également utiliser la fonction normaliser l'espace pour nettoyer les espaces blancs parasites autour du nom de la classe (comme mentionné par @Terry):

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

Notez que dans toutes ces versions, le * devrait être remplacé par le nom d'élément que vous souhaitez réellement faire correspondre, sauf si vous souhaitez rechercher chaque élément du document pour la condition donnée.

meder omuraliev
la source
37
@meder: Plus comme //div[contains(concat(' ', @class, ' '), ' Test ')]- Le vôtre affichera également des correspondances partielles.
Tomalak
5
Pourquoi ne faites-vous pas juste // div [@ class = 'Test']
Jessica
11
Parce que les classes peuvent contenir plus d'une valeur
meder omuraliev
8
Je suis surpris que xpath n'ait pas de raccourci / un moyen plus efficace de localiser un jeton dans une liste de jetons séparés par des espaces. Quelque chose dans les versions ultérieures de xpath?
thomasrutter
1
@thomasrutter pourquoi la surprise - c'est juste un langage fait pour XML, pas le HTML plus spécifique, et qui peut dire qu'il est décontracté d'utiliser des listes séparées par des espaces comme n'importe quelle valeur de nœud en XML. La solution de Tomalak est très viable.
bitoolean
152

Le moyen le plus simple ..

//div[@class="Test"]

En supposant que vous vouliez trouver <div class="Test">comme décrit.

Olli Puljula
la source
3
La syntaxe ci-dessus est beaucoup plus facile à utiliser et moins sujette aux erreurs. N'OUBLIEZ PAS que vous devez avoir les DOUBLES CITATIONS dans la classe pour chercher. Je recommanderais d'utiliser la liste ci-dessus. // div [@ class = "Test"]
FlyingV
Est-ce que cela fonctionne pour les cas où div [class = 'Test'] se situe à un niveau plus profond?
Jake0x32
1
@ Jake0x32, c'est parce qu'il utilise //non seulement /.
Solomon Ucko
7
Correspond-elle aussi à <<div class = "Test some-other-class">?
Jugal Thakkar
11
@JugalThakkar Non, ce n'est pas le cas. Il nécessite une correspondance exacte pour fonctionner, mais vous pouvez essayer à la place // div [contains (@class, "Test")].
Olli Puljula
29

La SEULE bonne façon de le faire avec XPath:

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

La fonction normalize-spacesupprime les espaces blancs de début et de fin et remplace également les séquences de caractères d'espaces blancs par un seul espace.


Remarque

Si vous n'avez pas besoin de beaucoup de ces requêtes Xpath, vous voudrez peut-être utiliser une bibliothèque qui convertit les sélecteurs CSS en XPath, car les sélecteurs CSS sont généralement beaucoup plus faciles à lire et à écrire que les requêtes XPath. Par exemple, dans ce cas, vous pouvez utiliser les deux div[class~="Test"]et div.Testpour obtenir le même résultat.

Quelques bibliothèques que j'ai pu trouver:

John Slegers
la source
24

Je fournis simplement ceci comme une réponse, comme Tomalak a fourni un commentaire à la réponse de Meder il y a longtemps

//div[contains(concat(' ', @class, ' '), ' Test ')]
Alex Lyman
la source
3
Désolé de revenir sur ce sujet il y a si longtemps, mais qu'en est-il concat(' ', normalize-space(@class), ' ')de toutes les sortes de caractères d'espace blanc?
Terry
Par curiosité - Pourquoi //div[contains(concat(' ', @class, ' '), ' Test ')]/chidne sélectionne- t- il pas les enfants?
Fusion
@Fusion si vous postez cela comme une question, vous pourriez obtenir une réponse.
bitoolean
@bitoolean étant le capitaine Cbvious est difficile ces jours-ci
Fusion
@Fusion J'essayais juste d'aider. XPath n'est pas un langage HTML. C'est plus générique, XML uniquement. Je n'ai aucune expérience dans ce domaine, mais je pense que vous supposez que vous pouvez simplement mettre l'ID au lieu de la balise. Vous devez sélectionner la valeur de l'attribut "id". Vous devez donc considérer le document HTML comme XML. Les discussions hors sujet n'aident pas les gens à trouver des solutions.
bitoolean
1

Une fonction utile peut être établie à partir des réponses précédentes:

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

Concattez ensuite l'appel de fonction dans votre requête.

Carcigenicate
la source
Ce code ne fonctionnerait qu'en PHP. Vous auriez pu le mentionner.
bitoolean
0

Match contre une classe qui a des espaces.

<div class="hello "></div>
//div[normalize-space(@class)="hello"]
Philippe
la source
-6

vous pouvez trouver des éléments comme cet exemple (tous les éléments css)

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