XPath était au départ un langage permettant essentiellement de décrire des ensembles de nœuds dans un document XML. La version 1.0 de XPath comprenait quelques fonctions pour la manipulation de nombres et de chaînes de caractères. L'objectif était alors de pouvoir comparer les contenus de nœuds. La version 2.0 de XPath a considérablement enrichi le langage. Il est devenu un langage beaucoup plus complet capable, par exemple, de manipuler des listes de nœuds et de valeurs atomiques.
XPath est uniquement un langage d'expressions dont l'évaluation donne des valeurs sans effet de bord. Il n'est pas possible dans XPath de mémoriser un résultat. XPath n'est donc pas un langage autonome et il est généralement utilisé au sein d'un langage hôte comme XSLT.
Il n'existe pas de variables propres à XPath mais une expression
XPath peut référencer des variables du langage hôte. Les valeurs de ces
variables sont alors utilisées pour évaluer l'expression. L'affectation
de valeurs à ces variables se fait uniquement au niveau du langage hôte.
Le langage XPath utilise aussi des variables propres particulières qui
servent à parcourir des listes. Ces variables s'apparentent aux
variables du langage hôte car elles ne sont jamais affectées
explicitement. Leur portée est en outre toujours limitée à un opérateur
d'itération comme for.
Le cœur de XPath est formé des expressions de chemins permettant
de décrire des ensembles de nœuds d'un document XML. Ces expressions
ressemblent aux chemins Unix pour nommer des fichiers
dans une arborescence.
Il a été vu au chapitre sur la syntaxe que les éléments d'un document XML sont reliés par des liens de parenté. Un élément est le parent d'un autre élément s'il le contient. Ces relations de parenté constituent l'arbre des éléments. Cette structure d'arbre est étendue à tous les constituants d'un document pour former l'arbre du document qui inclut les éléments et leurs contenus, les attributs, les instructions de traitement et les commentaires. C'est sous cette forme d'arbre que le document XML est manipulé par XPath et XSLT.
L'arbre d'un document est formé de nœuds de différentes sortes qui correspondent aux différents constituants du document. Ces sortes de nœuds sont les suivantes.
Le nœud racine de l'arbre d'un document est un nœud particulier appelé document node ou root node dans la terminologie de XPath 1.0. Ce nœud ne doit pas être confondu avec l'élément racine qui est un enfant de ce document node.
Chaque élément du document est représenté un nœud de cette sorte. Le contenu texte de l'élément n'est pas contenu dans ce nœud mais dans des nœuds textuels.
Chaque attribut est représenté par un nœud de cette sorte dont le parent est le nœud de l'élément ayant cet attribut. La valeur de l'attribut est contenue dans le nœud.
Chaque commentaire du document est représenté par un nœud de cette sorte qui contient le texte du commentaire.
Chaque instruction de traitement est représentée par un nœud de cette sorte qui contient le texte de l'instruction.
Ces nœuds dits textuels encapsulent le contenu texte des éléments. Le contenu textuel d'un élément est réparti dans plusieurs nœuds de cette sorte lorsque l'élément contient aussi d'autres éléments, des commentaires ou des instructions de traitement qui scindent le contenu textuel en plusieurs fragments.
Les nœuds de cette sorte représentent les espaces de noms déclarés dans un élément.
Afin d'illustrer ces sortes de nœuds, voici ci-dessous un document XML très simple ainsi que son arbre.
<?xml version="1.0" encoding="iso-8859-1"?> <!-- Time-stamp: "tree.xml 14 Feb 2008 09:29:00" --> <?xml-stylesheet href="tree.xsl" type="text/xsl"?> <list type="technical"> <item key="id001" lang="fr"> XML & Co </item> <item> <!-- Un commentaire inutile --> Du texte </item> et encore du texte à la fin. </list>
Dans la figure ci-dessous, chaque nœud de l'arbre est représenté par un rectangle contenant trois informations. La première information est la sorte du nœud, la deuxième est le nom éventuel du nœud et la troisième est la valeur textuelle du nœud.
Les nœuds de l'arbre d'un document sont caractérisés par un certain nombre de propriétés. Suivant les sortes de nœuds, certaines propriétés n'ont pas de sens et elles n'ont alors pas de valeur. À titre d'exemple, le nœud d'un commentaire n'a pas de nom.
Pour le nœud d'un élément, d'un attribut ou d'une instruction de traitement, le nom est bien sûr le nom de l'élément, de l'attribut ou de l'instruction. Les nœuds des commentaires et les nœuds textuels n'ont pas de nom. Le nœud racine n'a également pas de nom.
Tout nœud à l'exception du nœud racine a un parent qui est soit le nœud racine soit le nœud de l'élément qui le contient. La relation parent/enfant n'est pas symétrique en XML. Bien que le parent d'un attribut soit l'élément qui le contienne, l'attribut n'est pas considéré comme un enfant de cet élément (cf. propriété suivante).
Seuls le nœud racine et les nœuds des éléments peuvent avoir des enfants. Les enfants d'un nœud sont les nœuds des éléments, des instructions de traitement et des commentaires ainsi que les nœuds textuels qu'il contient. Les attributs ne font pas partie des enfants d'un élément. L'élément racine est un enfant du nœud racine qui peut aussi avoir des instructions de traitement et des commentaires comme enfants.
Chaque nœud de l'arbre du document XML a une valeur qui est une chaîne de caractères Unicode. Pour un élément, cette valeur textuelle est le résultat de la concaténation du texte contenu de l'élément en question et de ses descendants. Cette chaîne est aussi obtenue en supprimant du contenu de l'élément les balises de ses descendants, les instructions de traitement et les commentaires.
Pour un attribut, la valeur textuelle est la valeur de
l'attribut. Pour une instruction de traitement, c'est le texte qui
suit le nom de l'instruction. Pour un commentaire, c'est le texte
du commentaire sans les délimiteurs <!-- et
-->. La valeur textuelle d'un nœud textuel
est juste le texte qu'il contient.
Cette propriété n'existe que si le document a été un validé par un schéma. Il s'agit du type du contenu de l'élément ou de l'attribut qui a été attribué lors de la validation. Ce type peut être un type prédéfini pu un type défini dans le schéma.
Cette valeur n'existe que si le document a été un validé par un schéma.
Il existe des fonctions XPath permettant de récupérer les propriétés d'un nœud.
Fonctions sur les nœuds
xsd:string() name(node()? node)retourne le nom complet du nœud node ou du
nœud courant si node est absent.
xsd:string() local-name(node()? node)retourne le nom local du nœud node ou du
nœud courant si node est absent. Le nom local est
la partie du nom après le caractère ':' qui la
sépare du préfixe.
xsd:QName node-name(node()? node)retourne le nom qualifié du nœud node ou du
nœud courant si node est absent.
xsd:string base-uri(node()? node)retourne l'URI de
base du nœud node ou du nœud courant si
node est absent.
xsd:string string(node()? node)retourne la valeur textuelle du nœud node
ou du nœud courant si node est absent. Cette
fonction ne doit pas être confondue à la fonction
xsd:string qui convertit une valeur en
chaîne de caractère.
xsd:anyAtomicType* data(node()* list)retourne les valeurs typées des nœuds de la liste
list.
xsd:node root(node()? node)retourne la racine de l'arbre qui contient le nœud
node ou le nœud courant si
node est absent.
Les espaces de noms sont
manipulés en XPath 1.0 à travers l'axe namespace.
Cet axe est obsolète en XPath 2.0. Il est remplacé par des fonctions
permettant d'accéder aux espaces de noms.
xsd:string* namespace-uri(node()? node)retourne l'URi qui définit l'espace de noms dans lequel se
trouve le nœud node ou le nœud courant si
node est absent.
xsd:string* in-scope-prefixes(node()
node)retourne la liste des préfixes associés à un espace de noms
dans le nœud node. Si l'espace de noms par défaut
est défini, la liste contient la chaîne vide. La liste contient
toujours le préfixe xml associé à l'espace de
noms XML.
xsd:string namespace-uri-for-prefix(xsd:string prefix,
node() n)retourne l'URI qui définit l'espace de noms auquel est associé
le préfixe prefix dans le nœud
node.
for $i in in-scope-prefixes(.) return
concat($i, '=', namespace-uri-for-prefix($i, .))L'évaluation de cette expression donne une chaîne formée d'un
bloc de la forme
pour chaque espace de noms déclaré dans le nœud courant.prefixe=uri
Tous les nœuds d'un document XML sont classés suivant un ordre appelé ordre du document. Pour les éléments, cet ordre est celui du parcours préfixe de l'arbre du document. Ceci correspond à l'ordre des balises ouvrantes dans le document. Un élément est toujours placé après ses ancêtres et ses frères gauches et avant ses enfants et ses frères droits. Les attributs et les déclarations d'espaces de noms sont placés juste après leur élément et avant tout autre élément. Les déclarations d'espaces de noms sont placées avant les attributs. L'ordre relatif des déclarations d'espaces de noms et l'ordre relatif des attributs sont arbitraires mais ils restent fixes tout au long du traitement du document par une application.
L'ordre du document peut être manipulé explicitement par les
opérateurs XPath << et >>.
Il intervient aussi de façon implicite dans l'évaluation de certains
opérateurs, comme par exemple /, qui ordonnent les
nœuds de leur résultat suivant cet ordre.
Les expressions XPath manipulent des valeurs qui sont soit des nœuds de l'arbre d'un document XML, soit des valeurs atomiques. Les principales valeurs atomiques sont les entiers, les nombres flottants et les chaînes de caractères. La donnée universelle de XPath est la liste de valeurs. Ces listes ne peuvent pas être imbriquées. Une liste contient uniquement des valeurs et ne peut pas contenir une autre liste. La longueur de la liste est le nombre de valeurs qu'elle contient. Les valeurs de la liste sont ordonnées et chaque valeur a une position allant de 1 (et non pas 0) pour la première valeur à la longueur de la liste pour la dernière valeur.
Les listes peuvent être construites explicitement avec l'opérateur
XPath ',' (virgule). L'opérateur XSLT
xsl:sequence permet également de construire
explicitement des séquences. Beaucoup d'opérateurs et de fonctions XPath
retournent des listes comme valeurs.
Toute valeur est considérée par XPath comme une liste de longueur 1. Inversement, toute liste de longueur 1 est assimilée à l'unique valeur qu'elle contient.
Les valeurs atomiques comprennent les chaînes de caractères, les entiers, les nombres flottants et tous les types de base des schémas XML. Les types pour les valeurs atomiques sont les suivants.
xsd:string
Chaîne de caractères : 'string' ou "string"
xsd:boolean
Booléen : true() et false()
xsd:decimal
Nombre décimal : 3.14
xsd:float et xsd:double
Nombre flottant en simple ou double précision
xsd:integer
Entier : 42
xsd:duration, xsd:yearMonthDuration et
xsd:dayTimeDuration
Durée : P6Y4M2DT11H22M44S
xsd:dateTime, xsd:date et xsd:date
Date et heure : 2009-03-02T11:44:22
xsd:anyURI
URL : http:www.liafa.jussieu.fr/~carton/
xsd:anyType, xsd:anySimpleType et
xsd:anyAtomicType
Types racine de la hiérarchie
xsd:untyped et xsd:untypedAtomic
Nœud et valeur atomique non typée
L'évaluation d'une expression XPath se fait dans un contexte qui est fourni par le langage hôte. Le contexte se décompose en le contexte statique et le contexte dynamique. Cette distinction prend du sens lorsque les programmes du langage hôte sont susceptibles d'être compilé. Le contexte statique comprend tout ce qui peut être déterminé par une analyse statique du programme hôte. Tout ce qui dépend du document fait, au contraire, partie du contexte dynamique.
Les expressions XPath sont beaucoup utilisées dans les feuilles de style XSLT. Comme le langage XSLT est sans effet de bord, l'analyse statique des feuilles de styles XSLT est relativement facile et permet de déterminer beaucoup d'information.
On rappelle que la portée d'une déclaration est l'élément qui
contient cette déclaration. Pour une déclaration d'espace de noms, c'est l'élément
contenant l'attribut xmlns. Pour une déclaration de
variable XSLT, la portée est
l'élément parent de l'élément xsl:variable. La
portée d'une définition d'une fonction d'extension est toute la
feuille de style car ces définitions sont enfants de l'élément racine.
On dit qu'un objet est en portée dans une
expression XPath si l'expression est incluse dans la portée de l'objet
en question. Le contexte statique comprend les objets suivants
Tous les espaces de noms en portée, y compris éventuellement l'espace de noms par défaut. Le contexte comprend les associations entre les préfixes et les URL qui identifient les espaces de noms. Ceci permet de prendre en compte les noms qualifiés.
Toutes les variables en portée et leur type éventuel. Les valeurs de ces variables font partie du contexte dynamique.
Toutes les fonctions disponibles. Ceci comprend les fonctions standards de XPath, les fonctions de conversion de types et les fonctions d'extension définies au niveau du langage hôte.
Toutes collations en portée.
URI de base de l'élément.
Une collation est un ensemble de règles pour les comparaisons de caractères. Ces règles permettent de prendre en compte les spécificités régionales et linguistiques. La paire de lettres 'ss' et la lettre 'ß' sont, par exemple, considérées comme équivalentes en allemand. La collation définit en particulier l'ordre des lettres qui détermine l'ordre lexicographique. La collation par défaut est définie par les codes Unicode des lettres. La lettre 'Z' est, par exemple, avant la lettre 'a'.
La partie importante du contexte dynamique est appelée le focus et elle comprend trois objets valeurs appelées objet courant (context item dans la terminologie du W3C), position dans le contexte et taille du contexte. Le focus peut évoluer au cours de l'évaluation d'une expression.
L'objet courant est indispensable puisqu'il permet de résoudre
toutes les expressions relatives très souvent utilisées. C'est un peu
l'équivalent du current working directory d'un
shell Unix. L'expression @id retourne, par exemple,
l'attribut id du l'objet courant. L'objet courant
est très souvent un nœud du document mais il peut aussi être une valeur
atomique. Lorsque l'objet courant est un nœud, il est appelé le
nœud
courant. L'évaluation de certaines expressions, comme par
exemple @id, provoque une erreur si l'objet courant
n'est pas un nœud. L'objet courant est retourné par l'expression
XPath '.' (point).
Il est fréquent qu'une expression XPath soit évaluée pour
différentes valeurs de l'objet courant parcourant une liste d'objets.
Cette liste peut être déterminée avant l'évaluation ou au cours de
l'évaluation de l'expression XPath. La position du contexte donne la
position de l'objet courant dans cette liste implicite. Cette position
est retournée par la fonction XPath position(). La
taille du contexte est la longueur de cette liste implicite et elle est
retournée par la fonction XPath last().
Certains opérateurs XPath comme for,
some et every
introduisent des variables locales qui font partie du contexte
dynamique.
Les valeurs de toutes les variables en portée.
Toutes les définitions des fonctions d'extension.
Le premier objectif de XPath est, comme son nom l'indique, d'écrire des chemins dans l'arbre d'un document XML. Ces chemins décrivent des ensembles de nœuds du document qu'il est ainsi possible de manipuler. Le cœur de XPath est constitué des opérateurs de chemins qui permettent l'écriture des chemins.
Le type fondamental de XPath est la liste mais les opérateurs de chemins retournent des listes où les nœuds sont dans l'ordre du document et où chaque nœud a au plus une seule occurrence. Ces listes représentent en fait des ensembles de nœuds. Ce comportement assure un compatibilité avec XPath 1.0 qui manipule des ensembles de nœuds plutôt que des listes.
Il existe deux syntaxes, une explicite et une autre abrégée pour les expressions de chemins. La première facilite la compréhension mais la seconde, beaucoup plus concise, est généralement utilisée dans la pratique. La syntaxe abrégée est décrite en mais beaucoup d'exemples sont donnés avec les deux syntaxes pour une meilleure familiarisation avec les deux syntaxes.
Les expressions de cheminement permettent de se déplacer dans
l'arbre d'un document en passant d'un nœud à d'autres nœuds. Une
expression de cheminement a la forme
.
Elle retourne l'ensemble des nœuds du type
axe::typetype qui sont reliés au nœud courant par la
relation axe. Parmi tous les nœuds, l'axe
effectue une première sélection basée sur la position des nœuds dans
l'arbre par rapport au nœud courant. Le type raffine ensuite cette
sélection en se basant sur le type et le nom des nœuds. La sélection
peut encore être affinée par des filtres. Si l'objet courant
n'est pas un nœud, l'évaluation d'une telle expression provoque une
erreur. Les différents types correspondent aux différents nœuds pouvant
apparaître dans l'arbre d'un document. Les relations entre le nœud
courant et les nœuds retournés sont appelées axes
dans la terminologie XML.
L'axe par défaut est l'axe child qui
sélectionne les enfants du nœud courant.
node()tous les enfants du nœud courant
ancestor::*tous les ancêtres stricts du nœud courant
Chacun des axes donne une relation qui relie les nœuds sélectionnés par rapport au nœud courant. Les axes qu'il est possible d'utiliser dans les expressions XPath sont les suivants.
selfLe nœud lui-même (égalité)

childFils direct

parentParent

attributeAttribut du nœud
descendantDescendant strict

descendant-or-selfDescendant ou le nœud lui-même
ancestorAncêtre strict

ancestor-or-selfAncêtre ou le nœud lui-même
preceding-siblingFrère gauche (fils du même parent)

following-siblingFrère droit (fils du même parent)

precedingÀ gauche

followingÀ droite

namespaceEspace de noms du nœud
L'axe namespace est un héritage de XPath 1.0
qui doit être considéré comme obsolète. Il est conseillé d'utiliser
les fonctions XPath pour accéder aux espaces de noms d'un
nœud.
Les axes self, parent,
child, preceding-sibling et
following-sibling permettent de sélectionner le
nœud lui-même et les nœuds proches comme le montre la figure
ci-dessous.
Les cinq axes self,
ancestor, preceding,
descendant et following
partitionnent l'ensemble de tous les éléments du document en cinq
parties comme le montre la figure ci-dessous.
Une fois donné un axe, le type permet de restreindre l'ensemble des nœuds sélectionnés à un des nœuds d'une certaine forme. Les types possibles sont les suivants.
*
tous les éléments ou tous les attributs suivant l'axe utilisé
ns:*
tous les éléments ou tous les attributs (suivant l'axe) dans
l'espace de noms associé au préfixe
ns
*:local
tous les éléments ou tous les attributs (suivant l'axe)
de nom local local
name
les nœuds de nom name
(éléments ou attributs suivant l'axe utilisé)
node()
tous les nœuds
text()
tous les nœuds textuels
comment()
tous les commentaires
processing-instruction()
toutes les instructions de traitement
Les types node(), text(),
comment() et
processing-instruction() se présentent comme des
pseudo fonctions sans paramètre. Les parenthèses sont indispensables
car les expressions text et
text() et retournent des ensembles différents. Il
faut également distinguer l'expression string qui
s'évalue en une liste de nœuds des expressions
'string' et "string" qui
s'évaluent en une chaîne de caractères constante.
child::* ou *tous les éléments qui sont enfants du nœud courant
attribute::* ou @*tous les attributs du nœud courant
attribute::id ou @idattribut id du nœud courant
child::node() ou
node()tous les enfants du nœud courant
child::text ou texttous les éléments text qui sont enfants du
nœud courant
child::text() ou
text()
tous les nœuds textuels qui sont enfants du nœud courant
descendant::comment()tous les commentaires qui sont descendants du nœud courant, c'est-à-dire contenus dans le nœud courant
following::processing-instruction()tous les instructions de traitement qui suivent le nœud courant.
Les filtres permettent de sélectionner dans une liste les objets qui satisfont une condition. Ils apparaissent beaucoup dans les expressions de chemin pour restreindre le résultat d'une expression de cheminement. Nous donnons ici quelques exemples d'utilisation de ces filtres.
child::*[position() < 4] ou
*[position() < 4]
les trois premiers éléments enfants du nœud courant
attribute::*[name() != 'id'] ou
@*[name() != 'id']
tous les attributs autres que id
child::node()[position() = 4] ou
node()[4]
le quatrième enfant du nœud courant
child::section[position() = last()] ou
section[position() = last()]dernier enfant section du nœud
courant
descendant::item[attribute::id] ou
.//item[@id]
tous les descendants du nœud courant qui sont un élément
item ayant un attribut
id
ancestor::*[type='base']tous les ancêtres du nœud courant dont l'attribut
type existe et vaut
base.
L'opérateur '/' permet de composer des
expressions de cheminement pour créer de véritables chemins dans un
arbre XML. C'est un des opérateurs clé de XPath. Sa sémantique est
proche du même opérateur '/' des shell Unix mais il
est plus général et pas toujours facile à appréhender
Une expression de la forme
est évaluée de la façon suivante. L'expression
expr1/expr2expr1 est d'abord évaluée pour donner une
liste d'objets. Pour chacun des objets de cette liste, l'expression
expr2 est évaluée en modifiant dynamiquement
le focus de la façon suivante. L'objet courant est fixé à l'objet
choisi dans la liste, la position dans le contexte est fixée la position
de cet objet dans la liste et la taille du contexte est également fixée
à la taille de la liste. Les listes retournées par chacune des
évaluations de expr2, sont fusionnées pour
donner une liste de nœuds dans l'ordre du document et avec au plus une
occurrence de chaque nœud dans la liste. Cette liste est alors le
résultat de l'évaluation de
.
Si l'évaluation de expr1/expr2expr1 retourne la liste
vide, l'évaluation de
retourne aussi la liste vide. Le focus reprend, après l'évaluation, sa
valeur initiale.expr1/expr2
Supposons, par exemple, que l'expression
expr1 retourne la liste (n1, n2,
n3) formée de trois nœuds. L'expression
expr2 est donc évaluée trois fois. Elle est
évaluée une première fois en prenant le nœud courant égal à
n1, la position du contexte égale à 1 et la taille du
contexte égale à 3. Elle est évaluée une deuxième fois en prenant le
nœud courant égal à n2, la position du contexte égale
à 2 et la taille du contexte égale à 3. Elle est évaluée une troisième
et dernière fois en prenant le nœud courant égal à
n3, la position du contexte égale à 3 et la taille du
contexte égale à 3. Si ces trois évaluations retournent respectivement
les listes (n0, n2, n5), (n1) et
(n0, n1, n2, n4, n6) et que l'ordre du document est
n0, n1, n2, n4, n5, n6, le résultat de l'évaluation
est la liste (n0, n1, n2, n4, n5, n6).
self::node()/child::* ou ./*
tous les élements qui sont enfants du nœud courant
child::*/child::* ou */*
tous les éléments qui sont des enfants des enfants du nœud courant
child::p/child::em ou p/em
tous les éléments em enfants d'un élément
p enfant du nœud courant
child::*/attribute::* ou */@*
tous les attributs des éléments qui sont enfants du nœud courant
parent::*/parent::* ou ../..
le parent du parent du nœud courant
parent::*/child::* ou ../*
tous éléments qui sont frères du nœud courant, y compris le nœud courant
child::*/parent::* ou */..
le nœud courant s'il contient au moins un élément ou aucun nœud sinon
descendant::p/child::em ou .//p/em
tous les élements em qui sont enfants d'un
élément p descendant du nœud courant
descendant::*/descendant::* ou
descendant::*
tous les éléments descendants du nœud courant
ancestor::*/descendant::*tous les éléments du document
descendant::*/ancestor::*tous les ancêtres et tous les descendants du nœud courant ayant au moins un élément comme enfant si le nœud courant a au moins un élément comme enfant et aucun nœud sinon.
L'opérateur '/' peut être cascadé et il est
associatif à gauche. Une expression de la forme
est implicitement parenthésée
expr1/expr2/expr3(.
Ce parenthésage est très souvent inutile car l'opérateur
expr1/expr2)/expr3'/' est associatif à l'exception de quelques cas
pathologiques.
child::*/child::*/attribute::* ou
*/*/@*
tous les attributs des éléments qui sont des enfants des enfants du nœud courant
parent::*/child::*/descendant::text()
tous les nœuds textuels descendants d'un frère du nœud courant
L'opérateur '/' peut aussi être employé dans
des expressions de la forme
/ qui sont l'analogue
des chemins absolus dans les systèmes de fichiers.expr2
Une expression de la forme
/ est évaluée de la
façon suivante. L'expression expr2expr2 est évaluée en
ayant, au préalable, fixé le nœud courant à la racine de l'arbre
contenant le nœud courant, la position dans le contexte à 1 et la taille
du contexte à 1. Une telle expression est donc équivalente à une
expression root(.)/.
La fonction expr2root() retourne la racine de l'arbre
contenant son paramètre.
Le nœud courant appartient très souvent à l'arbre d'un document
XML. Dans ce cas, la racine de cet arbre est un nœud de la sorte
document node. Il est également possible que le
nœud courant appartienne à un fragment de document et que la racine de
cet arbre soit un nœud quelconque.
Les expressions de la forme
/ se comportent comme
des chemins absolus puiqu'elles s'évaluent en partant d'une racine.
Elles ne sont toutefois pas complètement absolues car la racine choisie
dépend du nœud courant. La racine choisie est celle de l'arbre
contenant le nœud courant.expr2
/
le nœud document node racine de
l'arbre
/child::* ou
/*
l'élément racine du document
/child::book ou
/book
l'élément racine du document si son nom est
book et aucun nœud sinon
/child::book/child:chapter ou
/book/chapter
les éléments chapter enfant de l'élément
racine du document si son nom est book et aucun
nœud sinon
/descendant::section ou
//section
tous les éléments section du document
Les opérateurs sur les ensembles réalisent les opérations d'union, d'intersection et de différences sur les ensembles de nœuds représentés par des listes classées dans l'ordre du document. L'opérateur d'union est très souvent utilisé alors que les deux autres opérateurs le sont plus rarement. Ces opérateurs fonctionnent uniquement avec des ensembles de nœuds. Ils ne fonctionnent pas avec des listes contenant des valeurs atomiques.
L'opérateur d'union est noté par le mot clé
union ou par le caractère '|'.
Les opérateurs d'intersection et de différence sont notés respectivement
par les mots clé intersect et
except.
child::* union attribute::* ou
* | @*
tous les attributs et tous les éléments enfants du nœud courant
*:* except xsl:*
tous les éléments enfants du nœud courant qui ne sont pas dans
l'espace de noms associé au préfixe xsl
Bien que les listes manipulées par XPath peuvent contenir des nœuds et des valeurs atomiques, les opérations ensemblistes ne peuvent être utilisées que sur des listes contenant uniquement des nœuds.
Le type booléen contient les deux valeurs true
et false. Ces deux valeurs sont retournées par les
fonctions true() et false() sans
paramètre. Les parenthèses sont obligatoires car l'expression XPath
true donne les éléments true
enfants du nœud courant.
Les valeurs booléennes peuvent être manipulées à l'aide des
opérateurs and et or et de la
fonction not().
true() and false()false
true() or false()true
not(false())true
Les valeurs des autres types peuvent être converties explicitement
en des valeurs booléennes par la fonction
xsd:boolean. Elles sont aussi converties
implicitement dès qu'une valeur booléenne est requise. C'est le cas,
par exemple, des filtres et de
la structure de contrôle if. Les
règles qui s'appliquent alors sont les suivantes.
Une liste vide est convertie en false.
Une liste vide non vide dont le premier élément est un nœud est
convertie en true.
Si la liste contient une seule valeur atomique, les règles suivantes s'appliquent. Rappelons qu'une valeur atomique est considérée comme une liste contenant cet objet et inversement.
Un nombre est convertie en true sauf s'il
vaut 0 ou NaN.
Une chaîne de caractères est convertie en
true sauf si elle est vide.
Les autres cas provoquent une erreur.
xsd:boolean(())donne false car la liste est vide
xsd:boolean((/,0))donne true car le premier objet de la
liste est un nœud
xsd:boolean(0)donne false car l'entier est égal à
0
xsd:boolean(7)donne true car l'entier est différent de
0
xsd:boolean('')donne false car la chaîne de caractères est
vide
xsd:boolean('string')donne true car la chaîne de caractères n'est
pas vide
Les seuls nombres existant en XPath 1.0 étaient les nombres
flottants. XPath 2.0 manipule les nombres des trois types
xsd:integer, xsd:decimal et
xsd:double des schémas XML.
Fonctions sur les nombres
'+', '-'
et '*'Ces opérateurs repectivement calculent la somme, la différence et le produit de deux nombres entiers, décimaux ou flottants.
2+3, 2-3, 2*35, -1, 6
divCet opérateur calcule le quotient de la division de deux nombres entiers, décimaux ou flottants.
3 div 2, 4.5 div 6.71.5, 0.671641791044776119
idiv et modCes opérateurs calculent respectivement le quotient et le reste de la division entière de deux entiers.
3 idiv 2, 3 mod 22, 1
number abs(number x)retourne la valeur absolue d'un nombre entier ou flottant. La valeur retournée est du même type que la valeur passée en paramètre.
abs(-1), abs(2.3)1, 2.3
number floor(number x)retourne la valeur entière approchée par valeur inférieure d'un nombre décimal ou flottant.
floor(1), floor(2.5), floor(2,7), floor(-2.5)
1, 2, 2, -3
number ceiling(number x)retourne la valeur entière approchée par valeur supérieure d'un nombre décimal ou flottant.
ceiling(1), ceiling(2.5), ceiling(2.3),
ceiling(-2.5)
1, 3, 3, -2
number round(number x)retourne la valeur entière approchée la plus proche d'un nombre décimal ou flottant. Si le paramètre est égal à n+1/2 pour un entier n, la valeur retournée est l'entier n+1.
round(1), round(2.4), round(2.5), round(-2.5)
1, 2, 3, -2
number round-half-to-even(number x,
xsd:integer? precision)retourne le multiple de 10-precision
le plus proche du nombre décimal ou flottant x.
La valeur par défaut de precision est
0. Dans ce cas, la fonction retourne l'entier le
plus proche de x. Si x est à
égale distance de deux multiples, c'est-à-dire si sa valeur est de la
forme (n+1/2)×10-precision, la fonction
retourne le multiple pair.
round-half-to-even(12.34,-1), round-half-to-even(12.34,1)
10, 12.3
round-half-to-even(2.5), round-half-to-even(3.5)
2, 4
xsd:anyAtomicType min(xsd:anyAtomicType*
list, xsd:string? col)retourne le minimum d'une liste de valeurs qui sont comparables
pour l'ordre <. Le paramètre optionel col
spécifie la collation à utiliser pour comparer des chaîne de
caractères.
min(1 to 6), min(('Hello', 'new', 'world'))
1, 'Hello'
xsd:anyAtomicType max(xsd:anyAtomicType*
list, xsd:string? col)retourne le maximum d'une liste de valeurs qui sont comparables
pour l'ordre lt. Le paramètre optionel
col spécifie la collation à utiliser pour comparer
des chaîne de caractères.
number sum(xsd:anyAtomicType* list)retourne la somme d'une liste de nombres. Les valeurs qui ne
sont pas des nombres sont converties au préalable en flottants avec
xsd:double.
sum(1 to 6)
21
number avg(xsd:anyAtomicType* list)retourne la moyenne d'une liste de nombres. Les valeurs qui ne
sont pas des nombres sont converties au préalable en flottants avec
xsd:double.
avg(1 to 6)
3.5
Les chaînes de caractères XPath contiennent, comme les documents XML, des caractères Unicode.
Une chaîne littérale est délimitée par une paire d'apostrophes
''' ou une paire de guillemets
'"'. Lorsqu'elle est délimitée par une paire
d'apostrophes, les guillemets sont autorisés à l'intérieur et les
apostrophes sont incluses en les doublant. Lorsqu'elle est, au
contraire, délimitée par une paire de guillemes, les apostrophes sont
autorisées à l'intérieur et les guillemets sont inclus en les
doublant.
'Une chaîne'donne Une chaine
'Une apostrophe '' et un guillemet "'donne Une apostrophe ' et un guillemet "
"Une apostrophe ' et un guillemet """donne Une apostrophe ' et un guillemet "
Les expressions XPath sont très souvent utilisées commme valeurs d'attributs d'un dialecte XML comme les schemas XML ou XSLT. Dans ce cas, les apostrophes ou les guillemets qui délimitent la valeur de l'attribut doivent être introduits avec les entités prédéfinies que cela soit comme délimiteur ou à l'intérieur d'une chaîne.
Il existe de nombreuses fonctions permettant de manipuler les
chaînes de caractères. Dans les exemples ci-dessous, les chaînes
apparaissant dans les valeurs des expressions sont écrites avec
délimiteurs ''' bien que ceux-ci ne fassent pas
partie des chaînes.
Fonctions sur les chaînes de caractères
xsd:integer string-length(xsd:string s)retourne la longueur de la chaîne de caractères, c'est-à-dire le nombre de caractères qui la composent.
string-length('Hello world')
11
xsd:string concat(xsd:string s1, xsd:string s2, xsd:string s3, ...)retourne la concaténation des chaînes de caractères
s1, s2, s3,
…. Le nombre de paramètres de cette fonction est
variable.
concat('Hello', 'new', 'world')
'Hellonewworld'
xsd:string string-join(xsd:string* list,
xsd:string sep)retourne la concaténation des chaînes de caractères de la liste
en insérant la chaîne sep entre elles.
Contrairement à la fonction concat, le nombre de
paramètres de cette fonction est fixé à 2 mais le premier paramètre
est une liste.
string-join(('Hello', 'new', 'world'), ' ')
'Hello new world'
xsd:integer compare(xsd:string s1, xsd:string s2,
xsd:anyURI? col)retourne la comparaison des deux chaînes de caractères
s1 et s2 en utilisant la
collation optionelle identifiée par l'URI col. La
valeur de retour est -1, 0 ou
1 suivant que s1 est avant
s2 pour l'ordre lexicographique, égale à
s2 ou après s2. Si
col est absente, la collation par défaut est
utilisée. Celle-ci est basée sur les codes Unicode.
compare('Hello', 'world')
-1
compare('hello', 'World')
1
xsd:boolean starts-with(xsd:string s, xsd:string prefix)retourne true si la chaîne
s commence par la chaîne prefix
et false sinon.
xsd:boolean ends-with(xsd:string s,
xsd:string suffix)retourne true si la chaîne
s se termine par la chaîne
suffix et false sinon.
xsd:boolean contains(xsd:string s,
xsd:string factor)retourne true si la chaîne
factor apparaît comme sous-chaîne dans la chaîne
s et false sinon.
contains('Hello', 'lo')
true
xsd:boolean matches(xsd:string s, xsd:string regexp,
xsd:string? flags)retourne true si une partie de la chaîne
s est compatible avec l'expression rationnelle
regexp et false sinon. La
chaîne optionelle flags précise comment doit être
effectuée l'opération.
matches('Hello world', '\w*')
true
matches('Hello world', '^\w*$')
false
xsd:string substring(xsd:string s, xsd:double start
xsd:double length)retourne la sous-chaîne commençant à la position
start et de longueur length ou
moins si la fin de la chaîne s est atteinte. Les
positions dans la chaîne sont numérotées à partir de
1. Les paramètres start et
length sont des flottants par compatibilité avec
XPath 1.0. Ils sont convertis en entiers avec
round().
substring('Hello world', 3, 5)
'llo w'
substring('Hello world', 7, 10)
'world'
xsd:string substring-before(xsd:string s1,
xsd:string s2)retourne la sous-chaîne de s1 avant
la première occurrence de la chaîne s2 dans
s1.
substring-before('Hello world', 'o')
'Hell'
substring-before('Hello world', 'ol')
''
xsd:string substring-after(xsd:string s1,
xsd:string s2)retourne la sous-chaîne de s1 après
la première occurrence de la chaîne s2 dans
s1.
substring-after('Hello world', 'o')
' world'
substring-after('Hello world', 'ol')
''
xsd:string replace(xsd:string s, xsd:string regexp,
xsd:string repl)retourne la chaîne de obtenue en remplaçant dans la chaîne
s l'occurrence de l'expression rationnelle
regexp par la chaîne repl.
L'expression regexp peut délimiter des blocs avec
des paires de parenthèses '(' et
')' qui peuvent ensuite être utilisés dans la
chaîne repl avec la syntaxe $1,
$2, ….
replace('Hello world', 'o', 'u')
'Hellu wurld'
replace('Hello world', 'world', 'orbi')
'Hello orbi'
replace('(code,1234)', '\(([^,]*),([^\)]*)\)', '($2,$1)')
'(1234,code)'
xsd:string* tokenize(xsd:string s,
xsd:string regexp)retourne la liste des chaînes obtenues en découpant la chaîne
s à chaque occurence de l'expression
regexp qui ne peut pas contenir la chaîne
vide.
tokenize('Hello new world', '\s+')
('Hello', 'new', 'world')
tokenize('Hello  world', '\s')
('Hello', '', 'world')
xsd:string normalize-space(xsd:string s)supprime les espaces en début et en fin de chaîne et remplace chaque suite d'espaces consécutifs par un seul espace. Les tabulations et les retours à la ligne sont considérés comme des espaces.
normalize-space(' Hello &x0A; world ')
'Hello world'
xsd:string lower-case(xsd:string s)retourne la chaîne s mise en
minuscule.
lower-case('Hello world')
'hello world'
xsd:string upper-case(xsd:string s)retourne la chaîne s mise en
majuscule.
upper-case('Hello world')
'HELLO WORLD'
xsd:string codepoints-to-string(xsd:integer* list)convertit une liste de codes Unicode en une chaîne de caractères.
codepoints-to-string((65, 8364, 48))
'A€0'
xsd:integer* string-to-codepoints(xsd:string s)convertit une chaîne de caractères en une liste de codes Unicode.
string-to-codepoints('A€0')
(65, 8364, 48)
xsd:string normalize-unicode(xsd:string s,
xsd:string? norm)retourne la normalisation de la chaîne
s avec la normalisation spécifiée par la chaîne
norm. Cette dernière peut prendre les valeurs
NFC, NFD,
NFKC et NFKD si le processeur
implémente chacune de ces normalisations. Si norm
est absente, la normalisation C (NFC) par défaut
et toujours implémentée est utilisée.
string-to-codepoints(normalize-unicode(codepoints-to-string((105, 776))))
(239)
La liste est la structure de données fondamentale de XPath. Il
existe plusieurs opérateurs permettant de construire et de manipuler des
listes. La restriction importante des listes XPath est qu'elles ne
peuvent pas être imbriquées. Une liste XPath ne peut pas contenir
d'autres listes. Elle peut uniquement contenir des nœuds et des valeurs
atomiques. Ainsi, l'expression ((1,2),(3,4,5)) ne
donne pas une liste contenant deux listes de deux et trois entiers. Elle
donne la liste de cinq entiers que donne également l'expression
(1,2,3,4,5).
L'opérateur essentiel de construction de listes est
',' (virgule) qui permet de concaténer, c'est-à-dire
mettre bout à bout, des listes. Il est aussi bien utilisé pour écrire
des listes constantes comme (1,2,3,4,5) que pour
concaténer les résultats d'autres expressions. Contrairement aux opérateurs de chemins, l'opérateur
',' ne réordonne pas les éléments des listes et ne
supprime pas les doublons. Le résultat de l'expression
est la nouvelle liste formée des valeurs du résultat de
expr1,expr2expr1 suivis des valeurs du résultat
l'expression expr2. Si une valeur apparaît
dans les deux résultats, elle a plusieurs occurrences dans le résultat
final. Par exemple, le résultat de l'expression
(1,2),(1,2) est bien la liste
(1,2,1,2) avec deux occurrences des entiers
1 et 2.
Le fait qu'une valeur soit assimilée à la liste (de longueur 1)
contenant cette valeur simplifie l'écriture des expressions. Ainsi les
deux expressions (1),(2) et 1,2
sont équivalentes. Cette identification entre une valeur et une liste
ne crée pas d'ambiguïté car les listes XPath ne peuvent pas être
imbriquées. Il n'y a pas de différence entre les deux expressions
((1),(2)) et (1,2).
L'opérateur to permet de créer une liste
contenant une suite d'entiers consécutifs. L'expression
donne la liste
n1 to
n2n1,n1+1,n1+2,…,n2-1,n2 des entiers de
n1 à n2
compris. Cet opérateur est surtout utile avec l'opérateur for pour
itérer sur une liste d'entiers.
1 to 5l'évaluation de cette expression donne la liste
(1,2,3,4,5)
1,2 to 4,5l'évaluation de cette expression donne la liste
(1,2,3,4,5)
Un filtre permet de sélectionner dans une liste les objets qui
satisfont une condition. Un filtre se présente comme une expression
entre des crochets '[' et ']'
placée après la liste à filtrer.
Une expression de la forme
est évaluée de la façon suivante. L'expression
expr1[expr2]expr1 est d'abord évaluée pour donner une
liste l d'objets. Pour chaque objet
o de la liste l,
l'expression expr2 est évaluée en modifiant,
au préalable, le focus de la manière suivante. L'objet courant est
fixé à l'objet o, la position du contexte est
fixée à la position de l'objet o dans la
liste l et la taille du contexte est fixée à
la taille de l. Le résultat de cette
évaluation est ensuite converti en une valeur booléenne en utilisant les
règles de conversion. Le
résultat final de l'évaluation de
est la liste des objets de expr1[expr2]l pour lesquels
expr2 s'est évaluée en la valeur
true. Les objets sélectionnés restent bien sûr dans
l'ordre de la liste l. La liste résultat est
en fait construite en supprimant de la liste
l les objets pour lesquels
expr2 s'évalue en
false.
Lors de l'évaluation de l'expression suivante, l'objet contexte
qui est retourné par '.' prend les valeurs
successives 1, 2,
3, 4 et 5.
Seules les valeurs paires satisfont la condition et sont
conservées.
(1 to 5)[. mod 2 = 0]l'évaluation de cette expression donne la liste
(2,4) des entiers pairs de la liste
Les filtres sont beaucoup utilisés dans les expression de chemin pour sélectionner des nœuds.
Plusieurs conditions peuvent être combinées à l'aide des opérateurs
booléens and et or. Les filtres
peuvent aussi être enchaînés en les mettant l'un après l'autre.
text[position() > 1 and position() < 4]
Les enfants text du nœud courant aux
positions 2 et 3
text[position() > 1][position() < 4]
Les enfants text du nœud courant aux
positions 2, 3 et 4
Le second exemple montre que les filtres peuvent être enchaînés.
Il ne donne pas le même résultat que le premier exemple car les
positions retournées par la fonction position() du
second filtre sont celles dans la liste obtenue après le premier filtre.
Comme le premier enfant text a été supprimé, il y a
un décalage d'une unité.
Il existe des fonctions XPath permettant de manipuler les listes.
xsd:integer count(item()* l)retourne la longueur de la liste l,
c'est-à-dire le nombre de nœuds ou valeurs atomiques qui la
composent.
count('Hello world', 1, 2, 3)
4
xsd:boolean empty(item()* l)retourne true si la liste
l est vide et false
sinon.
empty(1 to 5)
false
xsd:boolean exists(item()* l)retourne true si la liste
l est non vide et false
sinon.
exists(1 to 5)
true
item()* distinct-values(item()* l)retourne une liste des valeurs distinctes de la liste
l en supprimant les valeurs égales pour
l'opérateur eq.
distinct-values((1, 'Hello', 0, 1, 'World'))
(1, 'Hello', 0, 'World')
xsd:integer* index-of(item()* l, item() value)retourne la liste des positions de la valeur
value dans la liste l.
index-of((1, 'Hello', 0, 1, 'World'), 1)
(1, 4)
item()* subsequence(item()* l, xsd:double start
xsd:double length)retourne la sous-liste commençant à la position
start et de longueur length ou
moins si la fin de la liste l est
atteinte.
subsequence((1, 'Hello', 0, 1, 'World'), 2, 3)
('Hello', 0, 1)
item()* remove(item()* l, xsd:integer pos)retourne la liste obtenue en supprimant de la liste
l la valeur à la position
pos.
remove(1 to 5, 3)
(1, 2, 4, 5)
item()* insert-before(item()* l1, xsd:integer pos,
item()* l2)retourne la liste obtenue en insérant la liste
l2 dans la liste l1 à la
position pos.
insert-before(1 to 5, 3, 1 to 3)
(1, 2, 1, 2, 3, 3, 4, 5)
Les comparaisons entre les valeurs méritent une section entièrement
consacrée à elles seules. Elles jouent un rôle important en XPath car
elles permettent d'affiner la sélection des nœuds en prenant en compte
leurs contenus. Il est, par exemple, possible de sélectionner des
éléments d'un document dont la valeur d'un attribut satisfait une
condition comme dans les expressions
item[@type='free'] et list[@length <
5]. Les comparaisons sont aussi délicates à utiliser car leur
sémantique est source de pièges conduisant aisément à des programmes
erronés.
Il existe deux types d'opérateurs pour effectuer des comparaisons entre valeurs. Les premiers opérateurs dits généraux datent de la première version de XPath. Ils permettent de comparer deux valeurs quelconques, y compris des listes, avec des résultats parfois inattendus. Les seconds opérateurs ont été introduits avec la version 2.0 de XPath. Ils autorisent uniquement les comparaisons entres les valeurs atomiques de même type. Ils sont plus restrictifs mais leur comportement est beaucoup plus prévisible.
Il existe aussi l'opérateur is et les deux
opérateurs << et >>
permettant de tester l'égalité et l'ordre de nœuds dans le
document.
Les opérateurs pour les valeurs atomiques sont les opérateurs
eq, ne, lt,
le, gt et ge.
Ils permettent respectivement de tester l'égalité, la non-égalité,
l'ordre strict et l'ordre large (avec égalité) entre deux valeurs de
même type. L'ordre pour les entiers et les flottants est l'ordre
naturel alors que l'ordre pour les chaînes de caractères est l'ordre
lexicographique du dictionnaire. Cet ordre lexicographique prend en
compte les collations.
2 ne 3l'évaluation de cette expression donne
true
2 lt 3l'évaluation de cette expression donne
true
'chaine' ne 'string'l'évaluation de cette expression donne
true
'chaine' lt 'string'l'évaluation de cette expression donne
true
Les opérateurs pour les valeurs atomiques sont les opérateurs
=, !=, <,
<=, > et
>=. Ils permettent respectivement de tester
l'égalité, la non-égalité, l'ordre strict et l'ordre large de deux
valeurs de types quelconques.
L'opérateur is compare deux nœuds et retourne
true s'il s'agit du même nœud. C'est donc plus un
test d'identité que d'égalité. Il s'apparente plus à l'opéateur
== de Java qu'à la méthode
equals.
Les deux opérateurs << et
>> permettent de tester si un nœud se trouve
avant ou après un autre nœud dans l'ordre du document.
list is listcette expression donne true car il s'agit du
même nœud si l'élément courant a un seul enfant
list.
list << list/item[1]l'évaluation de cette expression donne true
car le père est avant ses enfants
list/item[1] << list/item[3]l'évaluation de cette expression donne
true
Des structures de contrôle sont apparues avec la version 2.0 de XPath. L'objectif n'est pas d'écrire des programmes complets en XPath. Il s'agit plutôt de remplacer par des expressions XPath simples des constructions plus lourdes des langages hôtes. Il est, par exemple, plus concis d'écrire le fragment XSLT suivant avec un test dans l'expression XPath
<a id="{if (@xml:id) then @xml:id else generate-id()}"/>
plutôt que le fragment équivalent suivant avec un test réalisé au niveau de XSLT.
<a>
<xsl:choose>
<xsl:when test="@xml:id">
<xsl:attribute name="id" select="@xml:id"/>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="id" select="generate-id()"/>
</xsl:otherwise>
</xsl:choose>
</a>
L'opérateur if permet d'effectuer un test. Sa
syntaxe est la suivante.
if (test) thenexpr1elseexpr2
La sémantique est celle de if dans tous les
langages de programmation. L'expression test
est évaluée et le résultat est converti en une valeur booléenne. Si
cette valeur booléenne est true, l'expression
expr1 est évaluée et le résultat est celui de
l'expression globale. Sinon, l'expression
expr2 est évaluée et le résultat est celui de
l'expression globale.
La partie else
est obligatoire et ne peut pas être omise. Lorsque cette seconde partie
est inutile, on met simplement expr2else ().
if (contains($url, ':')) then substring-before($url, ':')
else ''l'évaluation de cette expression retourne le protocole d'une
URL placé avant le caractère ':' si celle-ci en
contient un.
L'opérateur if est parfois remplacé par un
filtre. L'expression if (@xml:id) then @xml:id else
generate-id() est en effet équivalente à l'expression plus
concise (@xml:id, generate-id())[1].
L'opérateur for permet de parcourir des listes
pour construire une nouvelle liste. Il ne s'agit pas d'une structure de
contrôle pour des itérations quelconques comme le for
des langages C ou Java. Il s'apparente plus à l'opérateur
map des langages fonctionnels comme Caml qui permet
d'appliquer une fonction à chacun des objets d'une liste.
La syntaxe de l'opérateur for est la
suivante.
forvarinexpr1returnexpr2
L'évaluation d'une telle expression est réalisée de la façon
suivante. L'expression expr1 est d'abord
évaluée pour donner une liste de valeurs. Pour chacune de ces valeurs,
celle-ci est affectée à la variable var et
l'expression expr2 est évaluée. Le résultat
global est la liste obtenue en concaténant les listes obtenues pour
chacune des évaluations de l'expression
expr2.
Le résultat de l'expression expr2 est
une liste qui peut donc contribuer à plusieurs valeurs de la liste
finale. Si, au contraire, ce résultat est la liste vide, il n'y a
aucune contribution à la liste finale.
La variable var introduite par
l'opérateur for est une variable muette. Sa portée
est réduite à l'expression expr2 après le mot
clé return. Aucune valeur ne peut lui être affectée
directement.
for $i in 1 to 5 return $i * $il'évaluation de cette expression donne la liste
(1,4,9,16,25) des cinq premiers carrés
for $i in 1 to 3
return (2 * $i, 2 * $i + 1)l'évaluation de cette expression donne la liste
(2,3,4,5,6,7) qui est la concaténation des trois
listes (2,3), (4,5) et
(6,7)
for $i in 1 to 5 return
if ($i mod 2) then () else $i * $il'évaluation de cette expression donne la liste
(4,16) des carrés des deux nombres pairs 2 et 4
pour lesquels $i mod 2 donne
0
Il est possible d'imbriquer plusieurs opérateurs
for. Il y a d'ailleurs une syntaxe étendue qui
permet une écriture concise de ces itérations imbriquées. Cette syntaxe
prend la forme suivante.
forvar1inexpr1, …,varNinexprNreturnexpr0
Cette expression est en faite équivalente à l'expression suivante écrite avec la première syntaxe.
forvar1inexpr1return for … return forvarNinexprNreturnexpr0
for $i in 0 to 2, $j in 0 to 2
return $i * 3 + $jl'évaluation de cette expression donne la liste
(0,1,2,3,4,5,6,7,8) qui est la concaténation des
trois listes (0,1,2), (3,4,5)
et (6,7,8)
L'opérateur some permet de vérifier qu'au moins
un des objets d'une liste satisfait une condition. Sa syntaxe est la
suivante.
somevarinexpr1satisfiesexpr2
L'évaluation d'une telle expression est réalisée de la façon
suivante. L'expression expr1 est d'abord
évaluée pour donner une liste de valeurs. Pour chacune de ces valeurs,
celle-ci est affectée à la variable var et
l'expression expr2 est évaluée. Le résultat
de l'expression globale est true si au moins une des
évaluations de expr2 donne une valeur qui se
convertit en true. Il est égal à
false sinon.
some $i in 0 to 5 satisfies $i > 4l'évaluation de cette expression donne la valeur
true car la condition $i > 4
est satisfaite pour $i = 5
L'opérateur every permet de vérifier que tous
les objets d'une liste satisfont une condition. Sa syntaxe est la
suivante.
everyvarinexpr1satisfiesexpr2
L'évaluation d'une telle expression est réalisée de la façon
suivante. L'expression expr1 est d'abord
évaluée pour donner une liste de valeurs. Pour chacune de ces valeurs,
celle-ci est affectée à la variable var et
l'expression expr2 est évaluée. Le résultat
de l'expression globale est true si toutes les
évaluations de expr2 donnent une valeur qui
se convertit en true. Il est égal à
false sinon.
every $i in 0 to 5 satisfies $i > 4l'évaluation de cette expression donne la valeur
false car la condition $i >
4 n'est pas satisfaite pour $i = 0 ou
$i = 1
every $i in 0 to 5 satisfies
some $j in 0 to 5 satisfies $i + $j eq 5l'évaluation de cette expression donne la valeur
true
Les fonctions prédéfinis dans XPath sont les suivantes.
Les relations =, !=,
<, >,
<= et >= pour les
comparaisons.
Les opérateurs +, -,
*, div et mod
pour les opérations arithmétiques.
Les opérateurs and et or
ainsi que les fonctions boolénnes true(),
false() et not(...).
Les fonctions name(),
local-name(), count(),
position(), last(),
id().
Les fonctions sum(...),
floor(...), ceiling(...),
round(...).
Les fonctions boolean(...),
number(...), string(...) pour les
conversions de type.
Les constructions les plus fréquentes des expressions XPath peuvent être abrégées de façon à avoir des expressions plus concises. Les abréviations possibles sont les suivantes.
' 'l'axe child:: peut être omis.
..est l'abréviation de parent::node().
@est l'abréviation de attribute::.
//est l'abréviation de
descendant-or-self::node().
[n]
est l'abréviation de [position()=n] où n est
un entier.
En XPath 1.0, la formule '.' était une
abréviation pour self::node() et elle désignait
toujours un nœud. En XPath 2.0, elle désigne l'objet courant qui peut
être une valeur atomique ou un nœud.
Voici quelques exemples d'expressions XPath.
child::section[position()=2] ou section[2]
deuxième élément section fils du nœud courant.
descendant::p/following-sibling::em[position()=1] ou
.//p/following-sibling::em[1]
premier frère em d'un élément p descendant
du nœud courant.
child::section[child::title] ou section[title]
élément section fils du nœud courant et ayant un
fils title.
child::section[attribute::title] ou section[@title]
élément section fils du nœud courant et ayant un
attribut title.
child::section[attribute::title='Un titre'] ou
section[@title='Un titre']
élément section fils du nœud courant et ayant un
attribut title égal à la chaîne Un titre.
chapter[count(child::section) > 1]
élément chapter ayant plus d'un élément section
comme fils.
@*[name() != 'id']
attributs autres que l'attribut id.
section[2][@type='dual']
deuxième élément section du nœud courant si son attribut
type vaut dual.
L'application xmllint possède un interpréteur de commandes qui
est lancé avec l'option --shell. Il est alors possible de
naviguer dans le document XML et d'obtenir la valeur d'une expression XPath
comme dans l'exemple ci-dessous. La commande help de
l'interpréteur affiche toutes les commandes disponibles.
bash $ xmllint --shell bibliography.xml
/ > xpath bibliography/book[@lang='en']
Object is a Node Set :
Set contains 2 nodes:
1 ELEMENT book
ATTRIBUTE key
TEXT
content=Marchal00
ATTRIBUTE lang
TEXT
content=en
2 ELEMENT book
ATTRIBUTE key
TEXT
content=Zeldman03
ATTRIBUTE lang
TEXT
content=en
/ > cd bibliography/book[3]
book > xpath @lang
Object is a Node Set :
Set contains 1 nodes:
1 ATTRIBUTE lang
TEXT
content=fr
book > cd ..
bibliography >
| Opérateur | Action | Syntaxe | Exemples |
|---|---|---|---|
,
| Concaténation de listes |
E1,E2
|
1,'Two',3.14,true()
|
for
| Itération |
for $i in E1 return E2
|
for $i in 1 to 5 return $i * $i
|
some
| Quantification existentielle |
some $i in E1 satisfies E2
|
|
every
| Quantification universelle |
every $i in E1 satisfies E2
|
|
if
| Test |
if (E1) then E2 else E3
|
if ($x > 0) then $x else 0
|
/
| Enchaînement |
E1/E2
|
|
[ ]
| Prédicat |
E1[E2]
|
chapter[count(section) > 1]
|
and or not
| Opérations logiques |
E1 or E2
|
|
to
| Intervalle |
E1 to E2
|
1 to 5
|
eq ne lt le gt ge
| Comparaisons de valeurs atomiques |
E1 eq E2
|
$x lt $y
|
= != < <= > >=
| Comparaisons générales |
E1 = E2
|
$x < $y
|
<< is >>
| Comparaisons de nœuds |
E1 is E2
|
|
+ * - div idiv
| Opérations arithmétiques |
E1 + E2
|
$price * $qty
|
| union intersection except
| Opérations sur les listes de nœuds |
E1 | E2
|
/|*
|
instance of
cast as
castable as
treat as
| Changements de type |
E1 instance of type
|
$x instance of xsd:string
|