web-dev-qa-db-fra.com

XPath - Sélectionnez le premier élément après un autre élément

Je suis assez nouveau sur XPath, je bidouille avec lui depuis quelques heures maintenant, donc je ne sais pas vraiment si vous pouvez même faire quelque chose comme ceci avec.

D'accord, voici le scénario: Je veux trouver un lien depuis une page. Ce lien n'est reconnaissable que par sa valeur textuelle, c'est-à-dire. le texte entre les <a> balises (<a href="#"> ce lien <a>). Jusqu'à présent, j'ai réussi à mettre la main sur pour lier des éléments avec ce texte, le seul problème est qu'il y en a quelques-uns qui traînent.

Ces liens se trouvent dans des listes non ordonnées qui sont précédées d'une autre balise de lien, qui servirait vraiment de bon "ancre" point pour commencer la recherche de l'élément final que je veux trouver (c'est-à-dire alors je pourrais simplement accepter le premier qui correspond)

Pour clarifier un peu les choses, voici un exemple de ce qui se passe:

<a href="#">first dropdown menu</a>
<ul>
  <li><a href="#">some link</a></li>
  <li><a href="#">link i want to find</a></li>
</ul>

<-- *And i would actually want to find the thing from this list* --> 
<a href="#">second dropdown menu</a>
<ul>
  <li><a href="#">some link</a></li>
  <li><a href="#">link i want to find</a></li>
</ul>

Et je devrais probablement préciser que je ne veux recevoir qu'un seul résultat ou un ensemble de résultats, le premier élément étant l'élément "correct" - l'élément que je veux trouver.

EDIT: La question a déjà été répondue, mais il y avait quelques commentaires que je devrais préciser un peu plus, afin que les gens puissent réellement comprendre la question;)

L'idée était donc d'utiliser un élément pour spécifier l'emplacement d'un autre élément qui pourrait avoir des résultats de recherche en double dispersés tout autour du document.

Essentiellement, vous rencontreriez quelque chose comme ça si vous vouliez trouver un lien donné à partir d'un groupe de menus déroulants qui auraient des éléments avec les mêmes noms ou valeurs.

C'est essentiellement ça. Je sais que c'est encore un peu difficile de comprendre le sujet, mais malheureusement, j'ai du mal à mieux l'expliquer. Je suis sûr que quelqu'un d'autre pourrait faire un meilleur travail et si cela se produit, je suis plus qu'heureux d'inclure cette description ici.

43
JHollanti

J'ai dû lire votre question plusieurs fois, mais je pense que je la comprends. Ce qui vous intéresse, ce sont les prédicats. Les prédicats vous permettent de choisir des nœuds en fonction des conditions.

Par exemple, vous pourriez faire:

//a[text()='second dropdown menu']/following::ul[1]/li/a[text()='link i want to find']

cela sélectionnerait n'importe quelle ancre avec un certain texte, trouver le prochain ul, puis passer par ses enfants.

De plus, vous pouvez spécifier un index positionnel dans un jeu de résultats, le XPath suivant est une démonstration (mais cela ne résoudra pas votre problème):

//a[text()='first dropdown menu']/ul/li[last()]/a/text()

ou vous pouvez utiliser des axes pour naviguer entre frères et sœurs/ancêtres/enfants:

//a[ancestor::ul/preceding::a[1]/text() = 'second dropdown menu']/text()

Je ne suis donc pas sûr d'avoir bien compris votre question, mais cela devrait vous aider à rédiger votre XPath.

Fondamentalement, je suppose que votre XPath correspond à l'ancre dans plusieurs listes et vous voulez vous assurer de choisir la bonne. À un moment donné de votre XPath, vous avez besoin d'un prédicat pour spécifier une condition qui ne sera vraie que pour la liste dans laquelle se trouve votre nœud souhaité.

70
Chris Cameron-Mills

juste pour que je le comprenne bien: vous voulez le nœud "certains liens" après le "deuxième menu déroulant"

ul[preceding::a[text()='second dropdown menu' and position()=last()]]/li/a[text()='link i want to find']

cela devrait faire l'affaire (je ne suis pas sûr à 100% que vous devrez vérifier la position () = 1, mais je pense que si vous l'omettez, il correspondra à tous les ul suivants, car le précédent est "tous" les nœuds précédents - cela dépend du reste de votre structure xml)

5
Niko

Corrigez-moi si je me trompe - vous devez sélectionner "deuxième menu déroulant" dans l'exemple ci-dessus, mais le texte peut être dupliqué, vous n'avez donc besoin que d'un deuxième. XPath:

//a[text()='second drop down menu'][2]
0
Dewfy