Link Search Menu Expand Document

XPath - Localiser les données

Le chapitre précédent, peu technique, a surtout été l’occasion de faire connaissance avec le vocabulaire utilisé dans XPath. Je préfère vous prévenir, ce nouveau chapitre sera dense !

Nous allons aborder toutes les notions qui vous permettront d’utiliser XPath afin d’exploiter facilement vos documents XML. Au programme donc : la dissection détaillée d’une étape et un peu de pratique via EditiX.

Dissection d’une étape

Dans le chapitre précédent, nous avons vu qu’une expression XPath est en réalité une succession d’étapes. Nous allons maintenant nous intéresser de plus près à ce qu’est une étape.

Une étape est décrite par 3 éléments :

  • Un axe.
  • Un nœud ou un type de nœud.
  • Un ou plusieurs prédicats (facultatif).

Avant de voir en détail les valeurs possibles pour ces 3 éléments, je vous propose de revenir très rapidement sur leurs rôles respectifs.

L’axe

L’axe va nous permettre de définir le sens de la recherche. Par exemple, si l’on souhaite se diriger vers un nœud enfant ou au contraire remonter vers un nœud parent voir un ancêtre.

Le nœud

Ce second élément va nous permettre d’affiner notre recherche en indiquant explicitement le nom d’un nœud ou le type de nœud dont les informations nous intéressent.

Les prédicats

Comme précisé un peu plus haut, ce dernier élément est facultatif. Les prédicats, dont le nombre n’est pas limité, agissent comme un filtre et vont nous permettre de gagner en précision lors de nos recherches. Ainsi, grâce aux prédicats, il sera par exemple possible de sélectionner les informations à une position précise.

Maintenant que nous savons comment former une étape, il nous reste à apprendre la syntaxe nous permettant de les ordonner et ainsi de pouvoir écrire une étape compatible avec XPath :

axe::nœud[predicat][predicat]...[predicat]

Les axes

Comme nous l’avons vu dans la partie précédente, un axe est le premier élément formant une étape. Son rôle est de définir le sens de la recherche. Bien évidemment, le choix du sens est structuré par un vocabulaire précis que nous allons étudier maintenant.

Le tableau récapitulatif

Nom de l'axe Description
ancestor oriente la recherche vers les ancêtres du nœud courant
ancestor-or-self oriente la recherche vers le nœud courant et ses ancêtres
attribute oriente la recherche vers les attributs du nœud courant
child oriente la recherche vers les enfants du nœud courant
descendant oriente la recherche vers les descendants du nœud courant
descendant-or-self oriente la recherche vers le nœud courant et ses descendants
following oriente la recherche vers les nœuds suivant le nœud courant
following-sibling oriente la recherche vers les frères suivants du nœud courant
parent oriente la recherche vers le père du nœud courant
preceding oriente la recherche vers les nœuds précédant le nœud courant
preceding-sibling oriente la recherche vers les frères précédents du nœud courant
self oriente la recherche vers le nœud courant

Quelques abréviations

Tout au long de notre découverte des axes, des tests de nœuds et des prédicats, nous allons découvrir qu’il est possible d’utiliser des abréviations afin de rendre la syntaxe de nos expressions XPath plus claire et concise.

L’axe child

Pour les axes, il existe une abréviation possible et elle concerne l’axe child. En réalité, lorsque l’on souhaite orienter la recherche vers l’axe child, ce n’est pas nécessaire de le préciser. Il s’agit de l’axe par défaut.

Les tests de nœuds

Nous venons donc de voir les différentes valeurs possibles pour sélectionner un axe. Il est donc maintenant temps d’attaquer le second élément composant une étape : le nom d’un nœud ou le type de nœud.

Nom Description
nom du nœud oriente la recherche vers le nœud dont le nom a explicitement été spécifié
* oriente la recherche vers tous les nœuds
node() oriente la recherche vers tous les types de nœuds (éléments, commentaires, attributs, etc.)
text() oriente la recherche vers les nœuds de type texte
comment() oriente la recherche vers les nœuds de type commentaire

Quelques exemples

Puisque les prédicats sont facultatifs dans les expressions XPath, je vous propose de voir d’ores et déjà quelques exemples. Pour les exemples, nous allons nous appuyer sur le document XML que nous avons déjà utilisé :

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<repertoire>
  <!-- John DOE -->
  <personne sexe="masculin">
    <nom>DOE</nom>
    <prenom>John</prenom>
    <adresse>
      <numero>7</numero>
      <voie type="impasse">impasse du chemin</voie>
      <codePostal>75015</codePostal>
      <ville>PARIS</ville>
      <pays>FRANCE</pays>
    </adresse>
    <telephones>
      <telephone type="fixe">01 02 03 04 05</telephone>
      <telephone type="portable">06 07 08 09 10</telephone>
    </telephones>
    <emails>
      <email type="personnel">john.doe@wanadoo.fr</email>
      <email type="professionnel">john.doe@societe.com</email>
    </emails>
  </personne>
</repertoire>

Les chemins absolus

Nous allons débuter par des exemples se basant sur l’écriture d’une expression utilisant un chemin absolu.

Dans notre premier exemple, le but va être de récupérer le pays de domiciliation de John DOE. Commençons par décrire les étapes à suivre en français :

  • Étape 1 : descendre au nœud repertoire .
  • Étape 2 : descendre au nœud personne.
  • Étape 3 : descendre au nœud adresse.
  • Étape 4 : descendre au nœud pays.

Traduisons maintenant ces étapes sous la forme d’expressions XPath :

  • Étape 1 : child::repertoire.
  • Étape 2 : child::personne.
  • Étape 3 : child::adresse.
  • Étape 4 : child::pays.

Ce qui nous donne :

/child::repertoire/child::personne/child::adresse/child::pays

Il est possible de simplifier l’écriture de cette expression. En effet, comme je l’ai dit dans le chapitre sur les axes, l’axe child est celui par défaut, il n’est donc pas nécessaire de le préciser. Ainsi, il est possible de simplifier notre expression de la sorte :

/repertoire/personne/adresse/pays

Maintenant que vous êtes un peu plus à l’aise avec la syntaxe de XPath, je vous propose de voir un exemple un peu plus exotique. Le but est de trouver maintenant l’expression XPath permettant de trouver tous les commentaires de notre document XML.

Dans ce nouvel exemple, une seule étape est en réalité nécessaire et consiste à sélectionner tous les descendants du nœud racine qui sont des commentaires.

Tentons maintenant de traduire cette étape sous la forme d’expressions XPath :

  • On sélectionne tous les descendants avec l’expression descendant.
  • On filtre les commentaires avec l’expression comment().

Ce qui nous donne :

/descendant::comment()

Les chemins relatifs

Après avoir vu quelques exemples d’expressions XPath utilisant des chemins absolus, je vous propose de voir un exemple d’une expression utilisant un chemin relatif. Dans cet exemple, notre point de départ sera le nœud telephones. Une fois de plus, le but va être de récupérer le pays de domiciliation de John DOE. Commençons par décrire les étapes à suivre en français :

  • Étape 1 : remonter au nœud frère adresse.
  • Étape 2 : descendre au nœud pays.

Traduisons maintenant ces étapes sous la forme d’expressions XPath :

  • Étape 1 : preceding-sibling::adresse.
  • Étape 2 : pays.

Ce qui nous donne :

preceding-sibling::adresse/pays

Quelques abréviations

Tout comme pour les axes, il existe quelques abréviations dont je vous conseille d’abuser afin de rendre vos expressions XPath plus lisibles et légères.

L’expression /descendant-or-self::node()/

Dans nos expressions XPath, il est possible de remplacer l’expression /descendant-or-self::node()/ par //.

Ainsi, l’expression :

/descendant-or-self::node()/pays

peut être simplifiée par :

//pays

L’expression self::node()

Notre deuxième abréviation va nous permettre de remplacer l’expression /self::node()/ par ..

Ainsi, l’expression :

/repertoire/personne/self::node()

peut être simplifiée par :

/repertoire/personne/.

L’expression parent::node()

Notre dernière abréviation va nous permettre de remplacer l’expression /parent::node()/ par ...

Les prédicats

Nous venons donc de voir deux des trois éléments formant une étape dans une expression XPath. Dans ce chapitre, nous allons donc aborder l’élément manquant : les prédicats.

Le tableau récapitulatif

Nom du prédicat Description
attribute permet d'affiner la recherche en fonction d'un attribut
count() permet de compter le nombre de nœuds
last() permet de sélectionner le dernier nœud d'une liste
position() permet d'affiner la recherche en fonction de la position d'un nœud

Quelques exemples

Pour les exemples, nous allons continuer de nous appuyer sur le même document XML :

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<repertoire>
  <!-- John DOE -->
  <personne sexe="masculin">
    <nom>DOE</nom>
    <prenom>John</prenom>
    <adresse>
      <numero>7</numero>
      <voie type="impasse">impasse du chemin</voie>
      <codePostal>75015</codePostal>
      <ville>PARIS</ville>
      <pays>FRANCE</pays>
    </adresse>
    <telephones>
      <telephone type="fixe">01 02 03 04 05</telephone>
      <telephone type="portable">06 07 08 09 10</telephone>
    </telephones>
    <emails>
      <email type="personnel">john.doe@wanadoo.fr</email>
      <email type="professionnel">john.doe@societe.com</email>
    </emails>
  </personne>
</repertoire>

Premier exemple

Dans notre premier exemple, le but va être de récupérer le nœud contenant le numéro de téléphone fixe de John DOE. Bien évidemment, il existe plusieurs façons d’y arriver. Je vous propose d’utiliser celle qui pousse le moins à réfléchir : nous allons sélectionner tous les descendants du nœud racine et filtrer sur la valeur de l’attribut type. Ce qui nous donne :

/descendant::*[attribute::type="fixe"]

Bien évidemment, cette méthode est à proscrire car elle peut avoir de nombreux effets de bord. Il est possible de procéder autrement en précisant le chemin complet :

/repertoire/personne/telephones/telephone[attribute::type="fixe"]

Terminons ce premier exemple en sélectionnant les numéros de téléphones qui ne sont pas des numéros de téléphones fixes. Une fois de plus, il existe plusieurs façons de procéder. La première, qui a priori est la plus simple, consiste à remplacer dans notre expression précédente l’opérateur d’égalité = par l’opérateur de non égalité != :

/repertoire/personne/telephones/telephone[attribute::type!="fixe"]

Une autre méthode consiste à utiliser la fonction not() :

/repertoire/personne/telephones/telephone[not(attribute::type="fixe")]

A noter : la double négation nous fait revenir à notre point de départ. En effet, les 2 expressions suivantes sont équivalentes :

/repertoire/personne/telephones/telephone[not(attribute::type!="fixe")]
/repertoire/personne/telephones/telephone[attribute::type="fixe"]

Deuxième exemple

Après avoir manipulé les attributs, je vous propose maintenant de manipuler les positions. Ainsi, notre deuxième exemple consiste à sélectionner le premier numéro de téléphone de John DOE. Commençons par détailler les étapes en français :

  • Étape 1 : descendre au nœud repertoire.
  • Étape 2 : descendre au nœud personne.
  • Étape 3 : descendre au nœud telephones.
  • Étape 4 : sélectionner le premier nœud telephone.

Traduisons maintenant ces étapes sous la forme d’expressions XPath :

  • Étape 1 : repertoire.
  • Étape 2 : personne.
  • Étape 3 : telephones.
  • Étape 4 : telephone[position()=1].

Ce qui nous donne :

/repertoire/personne/telephones/telephone[position()=1]

Si l’on souhaite maintenant sélectionner le dernier nœud téléphone de la liste, on modifiera l’expression de la manière suivante :

/repertoire/personne/telephones/telephone[last()]

Quelques abréviations

Comme pour les axes, nous n’allons voir ici qu’une seule abréviation et elle concerne le prédicat attribute qu’il est possible de remplacer par le symbole @. Ainsi, l’expression :

/repertoire/personne/telephones/telephone[attribute::type="fixe"]

devient :

/repertoire/personne/telephones/telephone[@type="fixe"]

Un exemple avec EditiX

Pour conclure ce chapitre, je vous propose de voir comment exécuter une expression XPath avec EditiX.

Le document XML

Commencez par créer dans EditiX un document XML contenant les informations suivantes :

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>

<repertoire>
  <!-- John DOE -->
  <personne sexe="masculin">
    <nom>DOE</nom>
    <prenom>John</prenom>
    <adresse>
      <numero>7</numero>
      <voie type="impasse">impasse du chemin</voie>
      <codePostal>75015</codePostal>
      <ville>PARIS</ville>
      <pays>FRANCE</pays>
    </adresse>
    <telephones>
      <telephone type="fixe">01 02 03 04 05</telephone>
      <telephone type="portable">06 07 08 09 10</telephone>
    </telephones>
    <emails>
      <email type="personnel">john.doe@wanadoo.fr</email>
      <email type="professionnel">john.doe@societe.com</email>
    </emails>
  </personne>
    
  <!-- Marie POPPINS -->
  <personne sexe="feminin">
    <nom>POPPINS</nom>
    <prenom>Marie</prenom>
    <adresse>
      <numero>28</numero>
      <voie type="avenue">avenue de la république</voie>
      <codePostal>13005</codePostal>
      <ville>MARSEILLE</ville>
      <pays>FRANCE</pays>
    </adresse>
    <telephones>
      <telephone type="bureau">04 05 06 07 08</telephone>
    </telephones>
    <emails>
      <email type="professionnel">contact@poppins.fr</email>
    </emails>
  </personne>
</repertoire>

La vue XPath

Afin de pouvoir exécuter des expressions XPath, nous allons devoir afficher la vue dédiée au sein de EditiX. Pour ce faire, vous pouvez sélectionner dans la barre de menu XML puis XPath view ou encore utiliser le raccourci clavier Ctrl + Shift + 4.

La fenêtre suivante doit alors apparaître :

Vue XPath dans EditiX

Comme vous pouvez le constater, cette vue se compose de plusieurs éléments :

  • Un champ dans lequel toutes nos expressions seront écrites.
  • 2 boutons permettant de choisir si notre expression utilise un chemin relatif ou absolu.
  • Une puce permettant de choisir la version de XPath à utiliser (prenez l’habitude de travailler avec la version 2).
  • Des onglets permettant notamment d’afficher les informations sélectionnées par nos expressions.

Exécuter une requête

Dans cet ultime exemple, nous allons sélectionner les nœuds contenant des adresses e-mails professionnelles grâce à l’expression suivante :

/repertoire/personne/emails/email[attribute::type="professionnel"]

En théorie, nous devrions avoir 2nœuds sélectionnés. Vérifions tout de suite :

Résultat d'une expression XPath dans EditiX

Le résultat est bien celui souhaité ! 😉

En résumé

  • Une étape est composée d’un axe, d’un nœud ou type de nœud et d’un ou plusieurs prédicats.
  • L’axe par défaut est l’axe child.
  • De nombreuses abréviations permettent de simplifier l’écriture des expressions XPath.

Ce cours vous plait ?

Retrouvez ce cours en livre physique sur Amazon !