XPath: Comment sélectionner des éléments en fonction de leur valeur?

221

Je suis nouveau dans l'utilisation de XPath et cela peut être une question fondamentale. Veuillez me supporter et m'aider à résoudre le problème. J'ai un fichier XML comme celui-ci:

<RootNode>
  <FirstChild>
    <Element attribute1="abc" attribute2="xyz">Data</Element>
  <FirstChild>
</RootNode>

Je peux valider la présence d'un <Element>tag avec:

// Élément [@ attribute1 = "abc" et @ attribute2 = "xyz"]

Maintenant, je veux également vérifier la valeur de la balise pour la chaîne "Data". Pour y parvenir, on m'a dit d'utiliser:

// Élément [@ attribute1 = "abc" et @ attribute2 = "xyz" et Data]

Lorsque j'utilise l'expression ultérieure, j'obtiens l'erreur suivante:

Message d'échec de l'assertion: aucun nœud correspondant //Element[@attribute1="abc" and @attribute2="xyz" and Data]

Veuillez me donner votre avis sur la validité de l'expression XPath que j'ai utilisée. Sinon, quelle sera l'expression XPath valide?

vcosk
la source

Réponses:

329

La condition ci-dessous:

//Element[@attribute1="abc" and @attribute2="xyz" and Data]

vérifie l'existence de l'élément Data dans Element et non la valeur de l'élément Data.

Au lieu de cela, vous pouvez utiliser

//Element[@attribute1="abc" and @attribute2="xyz" and text()="Data"]
Utilisateur SO
la source
25
//Element[@attribute1="abc" and @attribute2="xyz" and .="Data"]

La raison pour laquelle j'ajoute cette réponse est que je veux expliquer la relation entre .et text().

La première chose est lors de l'utilisation [], il n'y a que deux types de données:

  1. [number] pour sélectionner un nœud dans l'ensemble de nœuds
  2. [bool] filtrer un ensemble de nœuds à partir d'un ensemble de nœuds

Dans ce cas, la valeur est évaluée à booléenne par fonction boolean(), et il existe une règle:

Les filtres sont toujours évalués par rapport à un contexte.

Lorsque vous devez comparer text()ou .avec une chaîne "Data", il utilise d'abord la string()fonction pour transformer ceux-ci en type chaîne, puis obtient un résultat booléen.

Il existe deux règles importantes concernant string():

  1. La string()fonction convertit un ensemble de nœuds en une chaîne en renvoyant la valeur de chaîne du premier nœud de l'ensemble de nœuds, ce qui peut dans certains cas donner des résultats inattendus.

    text()est un chemin relatif qui retourne un ensemble de nœuds contient tout le nœud de texte du nœud actuel (nœud de contexte), comme ["Data"]. Lorsqu'il est évalué par string(["Data"]), il renverra le premier nœud de l'ensemble de nœuds, de sorte que vous n'obtiendrez «Données» que s'il n'y a qu'un seul nœud de texte dans l'ensemble de nœuds.

  2. Si vous souhaitez que la string()fonction concatène tout le texte enfant, vous devez ensuite passer un seul nœud au lieu d'un ensemble de nœuds.

    Par exemple, nous obtenons un ensemble de nœuds ['a', 'b'], vous pouvez y passer le nœud parent string(parent), cela reviendra 'ab'et, string(.)dans votre cas, retournera une chaîne concaténée "Data".

Les deux sens n'obtiendront le même résultat que lorsqu'il y a un nœud de texte.

宏杰 李
la source