XPath
Un article de Mangue.org, l'encyclopéde libre.
| Sommaire |
XPath, un langage de requêtes
Tout comme XML, c'est un standard soutenu par le W3C (http://www.w3.org/), vous pouvez donc trouver le texte complet des recommandations concernant Xpath sur la page http://w3.org/TR/xpath . Il s'agit d'un langage de requêtes afin de questionner les documents XML. La syntaxe de des requêtes est documentée et standardisée et ne varie donc pas selon les parseurs utilisés. Il sera donc très rapide de passer d'une API à une autre ou même de changer de langage pour les traiter.
Une requête Xpath ressemble beaucoup à un chemin de fichiers. En effet, Comme nous l'avons vu dans l'introduction au XML, un tel document est représenté par un arbre. Il a donc un élément racine et des branches ; à l'intersection de deux branches, on trouve des noeuds. Pour repérer un élément dans un document XML, il suffit donc de donner le chemin complet de la racine de l'arbre jusqu'à l'élément. Comme sur les systèmes unixoïdes, la racine se note "/" ; pour écrire un chemin avec XPath, les éléments sont séparés par des barres obliques "/" (slash).
Reprenons l'exemple de document XML, que nous avons utilisé dans l'introduction :
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<!-- Balise racine -->
<livre>
<titre>Xml, XPath & Xslt</titre>
<!-- Premier chapitre -->
<chapitre titre="Introduction à l'XML">
<texte>
eXtensible Markup Language
5 > 3
</texte>
</chapitre>
<!-- Deuxième chapitre -->
<chapitre titre="Presentation de Xslt">
<texte>Pour formater un fichier XML</texte>
</chapitre>
</livre>
Par exemple, la requête :
/livre/chapitre/texte
renverra les éléments contenus dans les balises , tandis que la requête :
/livre/chapitre[@titre]/text()
renverra tous les titres des chapitres du livre. Afin de préciser les choses et de rentrer plus avant dans les possibilités d'XPath, le tableau ci-dessous donne des exemples simples de requêtes XPath, ainsi que leur résultat.
| Requête XPath | Résultat de la requête (sélection) |
| /livre | élément livre racine du document |
| ./texte | éléments texte du noeud courant |
| texte | éléments texte du noeud courant |
| ../texte | éléments fils texte du noeud parent |
| * | tous les éléments fils du noeud courant |
| ../* | tous les éléments au niveau du noeud parent (Y compris le noeud courant) |
| //texte | tous les éléments texte, quelque soit leur position dans l'arbre. |
| chapitre/texte | tous les éléments texte de tous les noeuds chapitres du noeud courant |
Lorsque l'on veut accéder aux attributs d'un élément XML, on fait précéder le nom de l'attribut d'un arobase, «@».
| Requête XPath | Résultat de la requête (sélection) |
| texte/@type | attribut type de tous les élements texte du noeud courant |
| texte/@* | tous les attributs de tous les élements texte du noeud courant |
| */@titre | tous les noeuds courants qui ont un attribut titre |
Comme vous l'avez sans doute remarqué l'étoile « * » est un caractère «joker», qui peut prendre toutes les valeurs possibles, l'étoile peut remplacer un nombre illimité de caractères ou même aucun.
Les axes
Les axes indiquent la direction d'un chemin. Les requêtes, qui ont déjà été présentées utilisent de manière implicite certains axes. Par exemple les deux points «..» font référence au noeud parent. Ceci correspond à l'axe Ancestor. Pour préciser un axe dans une requête XPath il suffit d'indiquer le type de l'axe suivit de deux symoboles « deux points » et du ou des noeuds à sélectionner : Axe::noeud.
| Axe | Définition |
| Ancestor | noeuds parents du noeud courant |
| ancestor-or-self | noeud courant ET ses noeuds parents |
| attribute | attributs du noeud courant |
| child | noeuds fils du noeud courant |
| descendant | noeuds fils des noeuds fils |
| descendant-or-self | noeud courant ET ses noeuds fils (//) |
| following | noeuds après le noeud courant |
| namespace | noeuds espace de nom du noeud courant |
| following-sibling | noeuds frères après le noeud courant |
| preceding | noeuds avant le noeud courant |
| self | noeud courant (.) |
Ainsi, on peut très bien écrire la même requête de différentes manières. Par exemple, les requêtes suivantes sont équivalentes :
child::chapitre <=> chapitre <=> ./chapitre
Toujours à titre d'exemple, preceding::* sélectionne tous les noeuds précèdant le noeud courant.
Les prédicats
Les prédicats permettent de rajouter des conditions à une requête XPath. En effet, il est souvent nécessaire de sélectionner des éléments en fonction de leur position dans l'arbre XML ou bien de la valeur d'un ou plusieurs de ses attributs, etc. Ce sont donc des filtres, que l'on rajoute à une expression XPath. Chaque prédicat doit être entouré de crochets. Il est également possible d'insérer plusieurs prédicats dans une expression XPath.
| Prédicat | Sélection |
| chapitre[texte] | éléments chapitre comportant un élément texte |
| chapitre[@titre='XPath'] | éléments chapitre comportant un un attribut titre avec la valeurs 'XPath' |
| chapitre[3] | élement chapitre à la 3eme position du document |
| chapitre[6][texte] | sixième élement chapitre du noeud courant s'il comporte un élément texte |
Pour affiner des requêtes Xpath, il est possible d'utiliser des opérateurs dans un prédicat.
| Opérateur XPath | Définition |
| = | Égalité |
| != | différence |
| > | supérieur |
| < | inférieur |
| >= | Supérieur ou égal |
| <= | Inférieur ou égal |
| and | « ET » logique |
| or | « ou » logique |
| Not() | Négation logique |
| + | addition |
| - | soustraction |
| div | Division |
| mod | Reste de la division entière (modulo) |
Voici un prédicat, qui sélectionne tous les noeuds chapitre du noeud courant ayant leur id supérieur à 3
chapitre[@id>3]
Les fonctions XPath
Pour permettre des requêtes XPath toujours plus subtiles et précises on peut avoir recours aux fonctions internes de XPath. Il existe 4 catégories de fonctions :
- fonctions pour les noeuds
- fonctions pour les chaînes de caractères
- fonctions pour les booléens
- fonctions pour les nombres
En les combinant avec des prédicats elles permettent d'appliquer des filtres très fins aux requêtes XPath et d'obtenir des informations suplémentaires sur un noeud tel que son espace de nom ou encore sa position.
| Fonctions sur les noeuds | Définitions |
| count(noeuds) | Retourne le nombre de noeuds |
| id(id) | Renvoie le noeud ayant l'identifiant id |
| last() | Renvoie true si le noeud est courant est le dernier |
| local-name(noeuds) | Renvoie les noms des noeuds sans l'espace de nom |
| name(noeuds) | Renvoie le nom complet |
| namespace-uri(noeuds) | Renvoie l'uri de l'espace de nom. |
| Fonctions sur les chaines de caractères | Définitions |
| concat(chaine, chaine, ...) | Concatène les chaines de caractères |
| contains(chaine1, chaine2) | Retourne vrai si la chaine1 contient la chaine2 |
| normalize-space(chaine) | Remplace les blancs multiples par un unique espace et suprime les espaces des extrémités sont suprimés |
| start-with(chaine1, chaine2) | Retourne vrai si la chaine1 commence avec les même caracrères de que la deuxième |
| string(var) | Retourne var sous forme d'une chaine de caracrères |
| string-lenght(chaine) | Retourne la longueure de la chaine |
| substring(chaine, offset, lenght) | Retourne la sous-chaine en fonction de l'offset et de la longueur |
| Fonctions sur les booléens | Définitions |
| boolean(var) | Convertit var en un booléen |
| not(var) | Retourne la négation de var |
| true() | Retourne vrai |
| false() | Retourne faux |
| lang(chaine) | Indique si chaine est de la langue du document |
| Fonctions sur les nombres | Définitions |
| number(var) | Convertit var en un nombre |
| sum(noeuds) | Retourne la somme des noeuds |
| floor(var) | Retourne le plus petit entier inférieur ou égal à var |
| ceiling(var) | Retourne le plus petit entier supérieur ou égal à var |
| round(var) | Retourne var sous forme d'entier le plus proche |
XSLT ajoute de nouvelles fonctions à XPath toutes aussi interressantes et qui offrent encore plus de possibilités. En effet il est possible d'interroger un autre document XML à partir d'une feuille de style grâce à la méthode document.
Exemples et test de Requêtes XPath
Nous allons étudier plusieurs exemples de requêtes XPath sur le document XML utilisé au début de ce tutoriel. Pour cela, nous allons utiliser un script Perl qui prend en argument (sur la ligne de commande) le chemin vers un fichier XML et une requête XPath, celui-ci renverra alors le résultat de la requête XPath appliquée au fichier XML.
Ce script peu s'avérer très utile pour tester des requêtes lors de la phase de développement d'un projet ou tout simplement pour bien comprendre comment fonctionnent les requêtes Xpath. Voici donc le code du script Perl TestRequete.pl . Il ne s'agit pas ici d'expliquer son fonctionnement, pour cela reportez vous à la documentation de Perl et de son module de gestion de XPath : XML::XPath disponible sur le CPAN (http://www.cpan.org/).
#!/usr/bin/perl use XML::XPath; use XML::XPath::XMLParser; use strict; # On récupère le nom du fichier XML et on le charge. my $xpath = XML::XPath->new( filename => shift @ARGV ); # On applique la requête XPath passée en argument. my $nodeset = $xpath->find( shift @ARGV ); #On affiche le résultat foreach my $node ( $nodeset->get_nodelist ) { print XML::XPath::XMLParser::as_string( $node ) . "n"; }
Nous allons maintenant voir quelques requêtes, qui pourrait servir pour la consultation d'un livre stocké sous la forme d'un document XML semblable à celui que nous avons vu. Pour consulter le titre du livre, la requête :
/livre/titre
renvoie
<titre>Xml, XPath & Xslt</titre>
et la requête
/livre/titre/text()
renvoie
Xml, XPath & Xslt
Pour compter le nombres de chapitres, on utilise la fonction Xpath count() pour les titres, il faut accéder à l'attribut titre des balises chapitre, on a donc les deux requêtes suivantes :
count( /livre/chapitre ) /livre/chapitre/@titre
Si on veut donner un aperçu de chaque chapitre, on peut aussi en présenter le début (les 100 premiers caractères par exemple), ceci se fait grâce à la fonction substring :
substring( /livre/chapitre/texte[1], 1, 100 )
Une fois toutes les informations récupérées il ne reste plus qu'à tout mettre en forme pour consulter le sommaire. Ceci peut se faire grâce à un programme développé par vos soins via l'API pour XML et XPath du langage que vous avez choisi. Cependant, il est également possible d'avoir recours aux transformations XSLT, qui permettent d'utiliser des requêtes Xpath dans les feuilles de style XSL.
Liens externes
-
Recommandation XPath du W3C (http://www.w3.org/TR/xpath)
-
Tutoriel sur XPath (http://www.zvon.org/xxl/XPathTutorial/General_fre/examples.html)
-
module XML::XPath sur CPAN (http://search.cpan.org/~msergeant/XML-XPath-1.13/XPath.pm)

