Le langage de requête XPATH
Présentation
♦ Le langage XPATH offre un moyen d'identifier un ensemble de noeuds dans un document
XML.
♦ Toutes les applications ayant besoin de repérer un fragment de document XML peuvent
utiliser ce langage.
♦ Les feuilles de style XSL, les pointers XPOINTER et les liens XLINK utilisent de manière
intensive les expressions XPATH.
♦ XPATH est un premier pas vers un langage d'interrogation d'une base de données XML
(XQuery).
Structure d'arbre d'un document XML
<!-- Texte -->
<stock>
<produit>
<nom> Livre </nom><prix monnaie="Francs"> 50 </prix>
<comment> Un commentaire </comment>
</produit>
<produit>
<nom> CD </nom><prix monnaie="Euros"> 23 </prix>
</produit>
<!-- Texte -->
</stock>
Les expressions XPATH
La forme générale d'une expression XPATH est
/sélecteur1/sélecteur2/... (exp. absolue)
sélecteur1/sélecteur2/... (exp. relative)
Chaque sélecteur sélectionne un ensemble de noeuds en fonction du résultat du sélecteur
précédent.
L'ensemble initial est soit le noeud courant (forme relative) soit la racine (forme absolue).
Exemple:
/stock/produit/comment
Les sélecteurs de noeuds
Les sélecteurs de noeuds sont de la forme :
axe::filtre[ condition1 ][ condition2 ]...
l'axe indique un sens de recherche,
le filtre sélectionne un type de noeud,
les conditions sélectionnent sur le contenu.
Les parties axe:: et [condition] sont optionnelles.
Les axes de recherche
Les axes en avant
Les axes qui permettent de descendre dans l'arbre:
child
les fils du noeud courant (c'est l'axe par défaut). C'est deux expressions sont
identiques :
produit/child::nom
produit/nom
self
le noeud courant,
/stock/produit[condition1]/self::produit[condition2]
descendant
les descendants du noeud courant
/stock/descendant::prix
descendant-or-self
les descendants du noeud courant plus lui-même.
Les axes en arrière
Les axes qui permettent de remonter dans l'arbre:
parent
le noeud parent du noeud courant (si il existe),
ancestor
les ascendants du noeud courant (dans l'exemple ci-dessous le noeud courant est le
nom du produit) :
ancestor::produit/prix
ancestor-or-self
que dire ?
Les axes à droite et à gauche
following-sibling
les noeuds frères placés après le noeud courant,
preceding-sibling
les noeuds frères placés avant le noeud courant,
Les axes avant et après
following
les noeuds placés après dans le document,
preceding
les noeuds placés avant dans le document,
Les axes pour les attributs
attribute
les noeuds de type attribut du noeud courant,
namespace
les noeuds de type espace de nom du noeud courant,
Les filtres
Filtrer les noeuds nommés
identificateur
les noeuds de l'axe qui portent ce nom.
/stock/produit/prix/attribute::monnaie
*
les noeuds de l'axe qui ont un nom (attribut ou élément)
/stock/*/prix/attribute::*
Filtrer les noeuds textuels
text()
tous les noeuds de type texte de l'axe.
/stock/produit/*/text()
Filtrer les commentaires
comment()
tous les noeuds de type commentaire de l'axe.
Filtrer les instructions de traitement
processing-instructions()
tous les noeuds de type instruction de traitement de l'axe,
Filtrer les noeuds
node()
tous les noeuds de l'axe sauf la racine,
/stock/produit/prix/node()
id(étiquettes)
les noeuds identifiés par au moins une des étiquettes,
id('CD')/prix
id('CD Voiture SX2500 CD')/prix
id(/reference/@ref)/prix
Les conditions
Rappel : les sélecteurs de noeuds sont de la forme :
axe::filtre[condition1][condition2]...
Condition d'existence
expression-xpath
vraie ssi l'expression renvoie un ensemble non vide de nœuds.
/stock/produit[ prix/attribute::monnaie ]
/stock/produit[ prix[attribute::monnaie ] ]
Ces expressions sélectionnent les noeuds produit à condition qu'un prix existe avec
l'attribut monnaieprécisé.
Condition de position
numéro
vraie ssi le noeud courant a cette position dans le contexte courant.
produit[ 2 ][ comment ]
produit[ comment ][ 2 ]
La première expression sélectionne les noeuds produit en deuxième position si il
possède un élément filscomment, la seconde sélectionne le deuxième
noeud produit qui possède un élément fil comment.
Les conditions logiques
Les relations portent sur deux sous-expressions XPATH :
exp1 relation exp2
vraie ssi il existe n1 (dans le résultat de exp1) et n2 (dans le résultat de exp2) qui
respectent la relation. Les relations possibles sont
= != < <= > >=
produit[prix = 100] (1)
produit[prix != 100] (2)
produit[prix < /stock/produit/prix] (3)
Explications : (1) les produits qui ont un prix à 100 ; (2) les produits qui ont un prix
différent de 100 ; (3) tous les produits sauf les plus onéreux.
condition1 and condition2
vraie ssi les deux conditions le sont également.
produit[prix > 10 and comment]
condition1 or condition2
vraie ssi au moins une des deux conditions est vraie.
not(condition)
vraie ssi la condition est fausse.
produit[not(prix != 100)]
tous les prix sont égaux à 100.
Fonctions & opérations
Les fonctions et opérations sont utilisables dans
les expressions logiques,
les clauses <xsl:value-of .../> des feuilles de style XSL.
Les types de base de XPATH
Il existe dans XPATH quatre types de base : booléen, chaîne de caractères, nombre réel,
ensemble de noeuds.
'chaine de caractères' ou "chaine de caractères"
constante chaîne de caractères.
produit[ (nom = 'CD') ]
100 ou 234.56
nombre réel (en virgule flottante).
produit[ (prix = 100) ]
true() ou false()
valeurs booléennes.
produit[ not(comment) = false() ]
Opérations et fonctions sur les nombres
+, -, mod, div,
opérations utilisables sur les nombres (traduction automatique).
produit[(prix div 10) = (prix mod 10)]
number( objet )
traduire l'objet sous la forme d'un nombre. Renvoie NaN si l'objet ne représente pas un
nombre.
produit[ (number(prix) = number(prix)) ]
sum( noeuds )
renvoie la somme des noeuds après les avoir transformés en nombre.
count( noeuds )
renvoie le nombre de noeuds.
floor( nombre )
arrondi par le bas.
ceiling( nombre )
arrondi par le haut.
round( nombre )
arrondi par le plus proche.
Fonctions sur les booléens
true()
toujours vraie.
false()
toujours fausse.
boolean( object )
vraie ssi l'objet est égale à la constante true() ou à la chaine "true".
not( boolean )
vraie ssi le paramètre est faux.
Fonctions sur les noeuds
last()
vraie ssi le noeud est le dernier du contexte courant.
position()
renvoie la position dans le contexte du noeud courant.
local-name( noeud )
renvoie la partie locale de l'étiquette d'un noeud.
namespace-uri( noeud )
renvoie la partie espace de nom de l'étiquette d'un noeud.
name( noeud )
renvoie l'étiquette d'un noeud.
id( chaines )
renvoie les noeuds identifiés par au moins une des étiquettes passées en paramètre.
Fonctions sur les chaînes
string( objet )
renvoie une version chaîne du paramètre.
concat( chaîne1, ..., chaîneN )
concaténation de chaînes.
string-length( chaîne )
renvoie la longueur d'une chaîne.
normalize-space( chaîne )
renvoie une version normalisée (suppression des blancs au début et à la fin et
remplacement de toute suite de blancs par un seul).
normalize-space(' AB CD E ') = 'AB CD E'
les blancs comprennent l'espace, le retour à la ligne (codes 10 et 13) et
la tabulation (code 9).
translate( ch1, ch2, ch3 )
renvoie une copie de ch1 dans laquelle les caractères présents dans ch2 sont
remplacés par les caractères de même position dans ch3.
translate('ABCD', 'AC', 'ac') = 'aBcD'
substring-before( ch1, ch2 )
renvoie la chaîne res définie par ch1 = res + ch2 + reste.
substring-after( ch1, ch2 )
renvoie la chaîne res définie par ch1 = reste + ch2 + res.
substring( chaîne, début ) et substring( chaîne, début, len )
extraction de sous-chaîne.
starts-with( ch1, ch2 )
vraie ssi ch1 débute par ch2.
contains( ch1, ch2 )
vraie ssi ch1 contient ch2.
Simplifications
Afin d'éviter une trop grande lourdeur, les simplifications suivantes sont autorisées :
originale simplifiée exemple
child:: /stock/produit
attribute:: @ /prix/@monnaie
/descendant-or-self::node()/ // //prix
self::node() . prix[. = 10]
parent::node() .. prix/../nom
[position() = x] [x] produits[4]
Exercices
Soit le document xml suivant :
<?xml version="1.0"?>
<AAA val="racine">
<BBB val="1"/>
<BBB val="2" id="id1" name="bbb"/>
<CCC val="3"/>
<BBB val="4">
<BBB val="4.1"/>
<CCC val="4.2">
<XXX val="4.2.1">
<YYY val="[Link]"/>
</XXX>
</CCC>
</BBB>
<DDD val="5">
<BBB val="5.1"/>
<CCC val="5.2"/>
<DDD val="5.3"/>
</DDD>
<CCC val="6"/>
<AAA val="7"/>
<CCC val="8">
<DDD val="8.1">
<BBB val="8.1.1" id="id2"/>
<BBB val="8.1.2" name=" bbb "/>
<EEE val="8.1.3"/>
<FFF val="8.1.4"/>
</DDD>
</CCC>
<CCC val="9">
<DDD val="9.1">
<BBB val="9.1.1">
<CCC val="[Link]"/>
<CCC val="[Link]"/>
</BBB>
<BBB val="9.1.2"/>
<EEE val="9.1.3" id="id3"/>
<FFF val="9.1.4" id="id4"/>
</DDD>
</CCC>
<BBB val="10" id="id5"/>
<DDDD val="11"/>
<EE val="12"/>
<EEE val="13"/>
</AAA>
Exercice 1 :
Ecrire les chemins XPath correspondant aux éléments suivants :
1) l'élément racine AAA
2) tous les éléments CCC qui sont enfants de l'élément racine AAA
3) tous les éléments BBB qui sont enfants de DDD, qui sont enfants de l'élément racine AAA
4) tous les éléments BBB
5) tous les éléments BBB qui sont enfants de DDD
6) tous les éléments inclus dans les éléments /AAA/CCC/DDD
7) tous les éléments BBB qui ont (exactement) trois ancêtres
8) tous les éléments
9) le premier élément BBB, fils de l'élément racine AAA
10) le dernier élément BBB, fils de l'élément racine AAA
11) tous les attributs id
12) tous les éléments BBB qui ont un attribut id
13) tous les éléments BBB qui ont un attribut name
14) tous les éléments BBB qui ont un attribut
15) tous les éléments BBB qui n'ont pas d'attribut id
16) tous les éléments BBB ayant un attribut id dont la valeur est id1
17) tous les éléments BBB ayant un attribut name dont la valeur est bbb
18) tous les éléments BBB ayant un attribut name dont la valeur est bbb.
19) les éléments ayant deux enfants BBB
20) les éléments ayant deux enfants
21) tous les éléments dont le nom commence par la lettre B
22) tous les éléments dont le nom contient la lettre C
23) tous les éléments qui ont un nom dont le nombre de caractères est exactement trois
24) tous les éléments qui ont un nom dont le nombre de caractères est strictement > 3
25) tous les éléments qui ont un nom de un ou deux caractères
26) tous les éléments CCC et BBB
27) tous les éléments EEE qui sont enfants de l'élément racine AAA et tous les éléments BBB
Exercice 2 :
Localiser dans le document les nœuds correspondant aux chemins XPath suivants :
1) /child::AAA
2) /child::AAA/child::BBB
3) /child::AAA/BBB
4) /descendant::*
5) /AAA/BBB/descendant::*
6) //CCC/descendant::*
7) //CCC/descendant::DDD
8) //DDD/parent::*
9) /AAA/BBB/DDD/CCC/EEE/ancestor::*
10) //FFF/ancestor::*
11) /AAA/BBB/following-sibling::*
12) //CCC/following-sibling::*
13) /AAA/BBB/preceding-sibling::*
14) //CCC/preceding-sibling::*
15) /AAA/AAA/following::*
16) /AAA/AAA/preceding::*
17) //CCC/preceding::*
18) /AAA/DDD/descendant-or-self::*
19) //CCC/descendant-or-self::*
20) /AAA/CCC/DDD/EEE/ancestor-or-self::*
21) //CCC/ancestor-or-self::*
22) //CCC/ancestor::*
23) //CCC/descendant::*
24) //CCC/following::*
25) //CCC/preceding::*
26) //CCC/self::*
27) //CCC/ancestor::* | // CCC /descendant::* | // CCC /following::* | // CCC /preceding::* | //
CCC /self::*
28) //BBB[position() mod 2 = 0 ]
29) //BBB[ position() = floor(last() div 2 + 0.5) or position() = ceiling(last() div 2 + 0.5) ]
30) //CCC[ position() = floor(last() div 2 + 0.5) or position() = ceiling(last() div 2 + 0.5) ]