0% ont trouvé ce document utile (0 vote)
5 vues48 pages

Introduction à XPath et ses nœuds XML

XPath est un langage d'expressions utilisé pour sélectionner des parties d'un document XML, intégrant des fonctionnalités pour manipuler des nœuds et des valeurs atomiques. Il fonctionne au sein d'un langage hôte et est essentiel pour des technologies comme XSLT. Les nœuds d'un document XML, tels que les éléments, attributs et textes, sont organisés en un arbre, et XPath permet de naviguer et d'extraire des données à partir de cette structure.

Transféré par

denis
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
5 vues48 pages

Introduction à XPath et ses nœuds XML

XPath est un langage d'expressions utilisé pour sélectionner des parties d'un document XML, intégrant des fonctionnalités pour manipuler des nœuds et des valeurs atomiques. Il fonctionne au sein d'un langage hôte et est essentiel pour des technologies comme XSLT. Les nœuds d'un document XML, tels que les éléments, attributs et textes, sont organisés en un arbre, et XPath permet de naviguer et d'extraire des données à partir de cette structure.

Transféré par

denis
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Chapitre 6.

XPath

XPath est un langage permettant de sélectionner des parties d'un document XML. Il est
utilisé dans de nombreux dialectes XML. Dans cet ouvrage, il est déjà apparu dans les
contraintes de cohérence [Section 5.12] des schémas XML. Le langage XSLT [Chapitre 7]
fait également un usage intensif de XPath pour désigner les parties à traiter.

Le langage XPath n'est pas un langage autonome. C'est un langage d'expressions utilisé au
sein d'un autre langage hôte. Il ressemble, dans cet aspect, aux expressions rationnelles,
appelées aussi expressions régulières qui est abrégé en regex telles qu'elles sont utilisées
dans les langages de script tels que Perl ou Python.

La syntaxe de XPath n'est pas une syntaxe XML car les expressions XPath apparaissent en
général comme valeurs d'attributs de documents XML. C'est en particulier le cas pour les
schémas, les schematrons et XSLT.

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. 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 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.

6.1. Données et environnement

Une expression XPath est généralement évaluée par rapport à un document XML pour en
sélectionner certaines parties. Le document XML est vu comme un arbre formé de nœuds.
Les principaux nœuds de cet arbre sont les éléments, les attributs et le texte du document
mais les commentaires et les instructions de traitement apparaissent aussi comme des
nœuds.

L'objet central de XPath est donc le nœud d'un document XML. XPath prend aussi

1
en compte les contenus des éléments et les valeurs des attributs pour effectuer des
sélections. Dans ce but, XPath manipule aussi des valeurs atomiques des types prédéfinis
[Section 5.5.1] des schémas : xsd:string, xsd:integer, xsd:decimal, xsd:date, xsd:time ....

6.1.1. Arbre d'un document XML

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érents types qui correspondent aux
différents constituants possibles d'un document. Ces types de nœuds font partie du système
de types [Section 6.1.4] de XPath. Ces types répartissent les nœuds en un nombre fini de
catégories. Ce type ne doit pas être confondu avec le type associé à un nœud lorsque le
document a été validé par un schéma. Ce dernier type est un type provenant du schéma.

document node (root node)

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.

element node
Chaque élément du document est représenté par un nœud de ce type. Le contenu texte
de l'élément n'est pas contenu dans ce nœud mais dans des nœuds textuels.

attribute node
Chaque attribut est représenté par un nœud de ce type 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.

comment node
Chaque commentaire du document est représenté par un nœud de ce type qui contient le
texte du commentaire.

processing instruction node


Chaque instruction de traitement est représentée par un nœud de ce type qui contient le
texte de l'instruction.

text node
Ces nœuds dits textuels encapsulent le contenu texte des éléments. Chaque fragment de
texte non intérrompu par un élément, une instruction de traitement ou un commentaire est
contenu dans un tel nœud. Le contenu textuel d'un élément est réparti dans plusieurs

2
nœuds de ce type 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.

namespace node
Les nœuds de ce type représentaient en XPath 1.0 les espaces de noms déclarés dans
un élément. Ils sont obsolètes et ne doivent plus être utilisés. Ils sont remplacés par des
fonctions XPath [Section [Link]].

Afin d'illustrer ces types de nœuds, voici ci-dessous un document XML très simple ainsi que
son arbre.

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 le type du nœud, la deuxième est
le nom éventuel du nœud et la troisième est la valeur textuelle du nœud.

Figure 6.1. Arbre d'un document XML

3
[Link]. Propriétés des nœuds
Les nœuds de l'arbre d'un document sont caractérisés par un certain nombre de propriétés.
Ces propriétés interviennent de façon essentielle dans la sélection des nœuds effectuée par
Xpath. Suivant les types 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.

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.

parent
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).

enfants
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.

valeur textuelle
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 des
contenus de tous les nœuds textuels qui sont descendants du nœud. Ce texte comprend
donc tout le texte contenu dans le nœud, y compris le texte contenu dans ses descendants.
De manière imagée, 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. La
valeur textuelle de l'élément p du fragment de document XML

<p>Texte en <i>italique</i> et en <b>gras <i>italique</i></b></p>

est donc la chaîne Texte en italique et en gras italique. La valeur textuelle est retournée
par l'instruction XSLT xsl:value-of.

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.

type

4
Cette propriété n'existe que si le document a été un validé par un schéma [Chapitre 5]. Il
s'agit du type attribué à l'élément ou à l'attribut lors de la validation par le schéma. Ce type
peut être un type prédéfini ou un type défini dans le schéma.

valeur typée
Cette valeur n'existe que si le document a été un validé par un schéma [Chapitre 5]. Il s'agit
de la valeur obtenue en convertissant la valeur textuelle dans le type du nœud. Si le type
d'un attribut est, par exemple, xsd:double et sa valeur textuelle est la chaîne 1.0e-3, sa
valeur est le nombre flottant 0.001. Cette conversion n'est possible que si le type du nœud
est un type simple.

Chaque nœud a une valeur qui est utilisée à chaque fois qu'un nœud apparaît là où une
valeur atomique est requise. Beaucoup de fonctions et d'opérateurs XPath prennent en
paramètre des valeurs atomiques. Lorsqu'un nœud est passé en paramètre à de tels
fonctions ou opérateurs, celui-ci est converti automatiquement en sa valeur.
Ce processus se déroule de la façon suivante. Si le nœud a une valeur typée (c'est-à-dire
lorsque le document est traité avec un schéma), la valeur est la valeur typée et son type est
celui de la valeur typée. Sinon, la valeur est la valeur textuelle du nœud et son type est
xsd:untypedAtomic. Cette conversion d'un nœud en valeur est appelée atomisation.

L'atomisation d'un nœud peut donner une liste de valeurs atomiques éventuellement vide.
C'est le cas lorsque le type du nœud est un type de listes comme le type prédéfini
xsd:IDREFS ou les types construits avec l'opérateur xsd:list [Section 5.6.6].

Lorsqu'une liste contenant des nœuds doit être convertie en une liste de valeurs, chacun
des nœuds est atomisé et sa valeur le remplace dans la liste. Lorsque la valeur du nœud
comporte plusieurs valeurs atomiques, celles-ci s'insèrent dans la liste à la place du nœud.

[Link]. Fonctions

Il existe des fonctions XPath permettant de récupérer les propriétés d'un nœud. Les
fonctions sont décrites avec leur type de retour et le type de leurs paramètres. Les types
utilisés sont ceux du système de typage [Section 6.1.4] de XPath. Lorsque le type du
paramètre est node()?, la fonction prend en paramètre un nœud ou rien. Dans ce
dernier cas, le paramètre est implicitement le nœud courant [Section [Link]].

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)

5
retourne le nom qualifié 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 avec la fonction xsd:string() [Section 6.1.6] qui convertit
une valeur en chaîne de caractères.

xsd:anyAtomicType* data(node()* list)


retourne les valeurs typées des nœuds de la liste list.

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.

node()* id(xsd:string s)
la chaîne s doit être une liste de noms XML séparés par des espaces. La fonction
retourne la liste des nœuds dont la valeur de l'attribut de type ID [Section 3.7.2] ou xsd:ID
[Section [Link]] est un des noms de la chaîne s. La valeur passée en paramètre est
souvent la valeur d'un attribut de type IDREF ou IDREFS. Pour qu'un attribut soit de type ID,
il doit être déclaré de ce type dans une DTD. Il est aussi possible d'utiliser l'attribut xml:id
[Section [Link]] qui est de type xsd:ID.

xsd:anyURI base-uri(node()? node)


retourne l'URI de base [Section [Link]] du nœud node ou du nœud courant si node est
absent.

xsd:anyURI document-uri(node()? node)


retourne l'URI de base [Section [Link]] du document contenant le nœud node ou le
nœud courant si node est absent.

xsd:anyURI resolve-uri(xsd:string? url, xsd:string? base)


combine l'URI uri avec l'URI de base base et retourne le résultat [Section 2.3.1]. Si l'URI
base est omise et que le langage hôte est XSLT, c'est l'URI de base de la feuille de style qui
est utilisée.

Les espaces de noms [Chapitre 4] 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)

6
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() node)


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, .))
donne une chaîne formée d'un bloc de la forme prefixe=uri pour chaque espace de
noms déclaré dans le nœud courant.

6.1.2. Ordre du document


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 '>>'
[Section 6.5.3]. Il intervient aussi de façon implicite dans l'évaluation de certains opérateurs,
comme par exemple '/' [Section 6.2.3], qui ordonnent les nœuds de leur résultat suivant cet
ordre.

6.1.3. Modèle de données

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 [Section 8.6.8] permet également de construire explicitement

7
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 contenant cette
valeur. Inversement, toute liste de longueur 1 est assimilée à l'unique valeur qu'elle contient.
Comme les listes ne peuvent pas être imbriquées, cette identification est assez naturelle et
elle ne conduit à aucune confusion.

Les valeurs atomiques comprennent les chaînes de caractères, les entiers, les nombres
flottants et tous les types prédéfinis [Section 5.5.1] des schémas XML. Les principaux types
pour les valeurs atomiques sont les suivants. Pour chacun d'entre eux, un exemple de
valeur est donné.

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 et double précision

xsd:integer
Entier : 42

xsd:duration, xsd:yearMonthDuration et xsd:dayTimeDuration


Durée : P6Y4M2DT11H22M44S de 6 ans, 4 mois, 2 jours, 11 heures 22 minutes et 44
secondes.

xsd:date, xsd:time et xsd:dateTime


Date et heure : 2009-03-02T[Link]

xsd:anyURI
URI : [Link]

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és

6.1.4. Typage

8
XPath possède un système de typage assez rudimentaire qui permet de décrire les types
des paramètres et le type de retour des fonctions. Ce système de typage est également
utilisé par XSLT pour donner le type d'une variable lors de sa déclaration et pour les types
de retour et des paramètres des fonctions d'extension. Les types des valeurs influent aussi
sur les comportement de certains opérateurs et en particulier des comparaisons [Section
6.5].

Ce système est organisé en une hiérarchie dont la racine est le type item() (avec les
parenthèses). Tous les autres types dérivent de ce type qui est le plus général. Toute valeur
manipulée par XPath est donc de ce type.

Il y a ensuite des types pour les nœuds et des types pour les valeurs atomiques. Pour les
nœuds, il y a d'abord un type générique node() ainsi que des types pour chacun des types
de nœuds [Section 6.1.1]. Ces types sont document-node(), element(), attribute(), text(),
processing-instruction() et comment() (avec les parenthèses). Les types pour les valeurs
atomiques sont les types prédéfinis [Section 5.5.1] des schémas comme xsd:integer.

Toute valeur atomique extraite du document par atomisation est typée. Lorsque le document
est validé par un schéma avant traitement par une feuille de style XSLT, les types des
valeurs atomiques des contenus d'éléments et des valeurs d'attributs sont donnés par le
schéma. Lorsque le document n'est pas validé par un schéma, toutes ces valeurs atomiques
provenant du document sont considérées du type xsd:untypedAtomic.

Le système de type possède trois opérateurs '?', '*' et '+', en notation postfixée, pour
construire de nouveaux types. Ils s'appliquent aux types pour les nœuds et les valeurs
atomiques décrits précédemment. L'opérateur '?' désigne un nouveau type autorisant
l'absence de valeur. Ces types sont surtout utilisés pour décrire les paramètres
optionnels des fonctions. La fonction XPath name() [Section [Link]] a, par exemple, un
paramètre de type node()?. Ceci signifie que son paramètre est soit un nœud soit rien.
L'opérateur '*' construit un nouveau type pour les listes. Le type xsd:integer* est, par
exemple, le type des listes d'entiers éventuellement vides. L'opérateur '+' construit un
nouveau type pour les listes non vides. Le type xsd:integer+ est, par exemple, le type des
listes non vides d'entiers.

6.1.5. Contexte

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és. 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'informations.

9
[Link]. Contexte statique

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 [Section 4.2], c'est l'élément contenant l'attribut xmlns.
Pour une déclaration de variable XSLT [Section 8.9], 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 [Section 8.10] 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 :

Espaces de noms
Tous les espaces de noms [Chapitre 4] en portée, y compris éventuellement l'espace de
noms par défaut. Le contexte comprend les associations entre les préfixes et les URI qui
identifient les espaces de noms. Ceci permet de prendre en compte les noms qualifiés.

Variables
Toutes les variables en portée et leur type éventuel. Les valeurs de ces variables font
partie du contexte dynamique.

Fonctions
Toutes les fonctions disponibles. Ceci comprend les fonctions standards de XPath, les
fonctions de conversion de types et les fonctions d'extension [Section 8.10] définies au
niveau du langage hôte.

Collations
Toutes les collations [Section 2.2.5] en portée.

URI de base
URI de base [Section [Link]] de l'élément.

[Link]. Contexte dynamique

La partie importante du contexte dynamique est appelée le focus et elle comprend trois
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. 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. C'est est un peu l'équivalent du current working directory d'un shell Unix.
L'expression @id retourne, par exemple, l'attribut id du 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).

10
Il est fréquent qu'une expression XPath soit évaluée pour différentes valeurs de l'objet
courant prises dans une liste. L'objet courant parcourt successivement les valeurs de cette
liste qui peut être déterminée avant l'évaluation ou au cours de l'évaluation de l'expression
XPath. Pour chaque valeur prise dans la liste par l'objet courant, la position dans le contexte
et la taille du contexte sont respectivement la position de la valeur dans liste et la taille de la
liste. La taille du contexte est bien sûr la même pour toutes les valeurs alors que la position
dans le contexte change pour chaque valeur. La position dans le contexte et sa taille sont
retournées par les deux fonctions XPath position() et last().

Variables locales
Certains opérateurs XPath comme for, some et every [Section 6.6.2] introduisent des
variables locales qui font partie du contexte dynamique.

Valeurs des variables


Les valeurs de toutes les variables [Section 8.9] en portée.

Définition des fonctions


Toutes les définitions des fonctions d'extension.

6.1.6. Fonctions de conversion

XSLT 1.0 possède une fonction number() pour convertir une valeur quelconque en un entier.

Pour chaque type de base des schémas comme xsd:boolean ou xsd:string, il existe une
fonction XPath de conversion ayant le même nom. Celle-ci convertit une valeur quelconque
en une valeur du type en question. La fonction xsd:boolean() convertit, par exemple, une
valeur en une valeur booléenne [Section 6.3.1].

6.1.7. Fonctions externes

Certaines fonctions pouvant être utilisées dans les expressions XPath sont, en réalité,
fournies par le langage hôte. Le langage XSLT fournit, en particulier, quelques fonctions très
utiles. Il permet également de définir de nouvelles fonctions.

xsd:string format-number(number n, xsd:string format, xsd:ID id)


retourne le nombre n formaté avec le format format où l'interprétation de ce format est
donné par l'élément xsl:decimal-format [Section 8.6.12] identifié par id.

xsd:string generate-id(node()? node)


retourne un identifiant pour le nœud node ou le nœud courant si node est absent. Au
cours d'un même traitement, plusieurs appels à generate-id avec le même paramètre
donnent le même identifiant. En revanche, des appels dans des traitements différents
peuvent conduire à des résultats différents. Cette fonction est souvent utilisée pour produire
une valeur destinée à un attribut de type ID ou xsd:ID comme xml:id

11
node() current()
retourne le nœud courant auquel s'applique la règle définie par l'élément XSLT
xsl:template.

node()* current-group()
retourne la liste des nœuds du groupe courant lors de l'utilisation de l'élément XSLT
xsl:for-each-group.

xsd:string current-grouping-key()
retourne la clé courante lors de l'utilisation de l'élément XSLT xsl:for-each-group.

xsd:string regexp-group(xsd:integer n)
retourne le fragment de texte entre une paire de parenthèses de l'expression rationnelle
lors de l'utilisation de l'élément XSLT xsl:matching-substring.

6.2. Expressions de chemins

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 une 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 [Section 6.7] mais
la plupart des exemples sont donnés avec les deux syntaxes pour une meilleure
familiarisation avec les deux syntaxes.

6.2.1. Expressions de cheminement

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
axe::type. Elle retourne l'ensemble des nœuds du type de nœud type 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 [Section 6.1.1].
La sélection peut encore être affinée par des filtres [Section 6.2.2]. Si l'objet courant n'est

12
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.

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, ce qui n'inclut pas les attributs

ancestor::*
tous les ancêtres stricts du nœud courant

[Link]. Axes

Chacun des axes donne une relation qui relie les nœuds sélectionnés au nœud courant. Les
axes qu'il est possible d'utiliser dans les expressions XPath sont les suivants.

self
Le nœud lui-même (égalité)

child
Enfant direct

13
parent
Parent

attribute
Attribut du nœud

descendant
Descendant strict

14
descendant-or-self
Descendant ou le nœud lui-même

15
16
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 [Section [Link]] pour accéder aux espaces de
noms d'un nœud. Les cinq axes self, parent, child, preceding-sibling et following-sibling
sélectionnent le nœud lui-même et les nœuds proches comme le montre la figure
ci-dessous. Les nœuds sélectionnés par ces cinq axes sont le nœud lui-même pour self, le
nœud juste au dessus pour parent, les nœuds juste en dessous pour child, les nœuds juste
à gauche pour preceding-sibling et les nœuds juste à droite pour following-sibling.

Figure 6.2. Nœuds proches

Au contraire, les quatre axes ancestor, preceding, descendant et following sélectionnent des
nœuds qui peuvent être très éloignés du nœud courant. Avec l'axe self, ces quatre axes
partitionnent l'ensemble de tous les nœuds du document en cinq zones disjointes comme le
montre la figure ci-dessous.

17
Figure 6.3. Partitionnement des éléments selon les cinq axes

[Link]. Types
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() ou processing-instruction(name)
toutes les instructions de traitement ou les instructions de traitement de nom name
Les types node(), text(), comment() et processing-instruction() se présentent comme des

18
pseudo fonctions sans paramètre. Les parenthèses sont indispensables car les expressions
text et text() s'évaluent différemment. L'expression text retourne les éléments de nom text
qui sont enfants du nœud courant alors que l'expression text() retourne les nœuds textuels
qui sont enfants du nœud courant. Il faut, également, distinguer l'expression string qui
s'évalue en une liste de nœuds de nom string des expressions 'string' et "string" qui
s'évaluent en une chaîne de caractères.

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 @id
attribut id du nœud courant

child::node() ou node()
tous les enfants du nœud courant

child::text ou text
tous les éléments de nom 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()
toutes les instructions de traitement qui suivent le nœud courant.

child::processing-instruction('xml-stylesheet')
toutes les instructions de traitement de nom xml-stylesheet qui sont enfants du nœud
courant.

6.2.2. Filtres des expressions de cheminement

Les filtres [Section 6.4.2] permettent de d'extraire d'une liste les objets qui satisfont une
condition pour former une nouvelle liste. 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. Lorsque ces expressions XPath apparaissent
comme valeur d'attributs, il est nécessaire de remplacer les caractères spéciaux
'<' et '>' par les entités prédéfinies.

child::*[position() < 4] ou *[position() < 4]


les trois premiers éléments enfants du nœud courant

19
attribute::*[name() != 'id'] ou @*[name() != 'id']
tous les attributs autres que id. Cette expression peut aussi être écrite @* except @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.

chapter[count(child::section) > 1]
élément chapter ayant au moins deux éléments section comme enfants.

6.2.3. Opérateur '/' de composition de chemins

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 expr1/expr2 est évaluée de la façon suivante. L'expression


expr1 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 [Section [Link]]
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
expr1/expr2. Si l'évaluation de expr1 retourne la liste vide, l'évaluation de expr1/expr2
retourne aussi la liste vide. Le focus reprend, après l'évaluation, sa valeur initiale.

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).

20
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.

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::*/position()
liste (1, 2, ..., n) où n est le nombre d'enfants du nœud courant.

L'opérateur '/' peut être cascadé et il est associatif à gauche. Une expression de la forme
expr1/expr2/ expr3 est implicitement parenthésée (expr1/expr2)/expr3. Ce parenthésage est
très souvent inutile car l'opérateur '/' est associatif à l'exception de quelques cas
pathologiques.

child::*/child::*/attribute::* ou */*/@*

21
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 /expr2 qui sont
l'analogue des chemins absolus dans les systèmes de fichiers.

Une expression de la forme /expr2 est évaluée de la façon suivante. L'expression expr2 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(.)/expr2. La fonction root() 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 type 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 /expr2 se comportent comme des chemins absolus puisqu'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.

/
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

6.2.4. Expressions ensemblistes

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.

22
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

@* except @id
tous les attributs excepté l'attribut id

descendant::* intersect descendant::p/following::*


tous les éléments descendants du nœud courant qui suivent un élément p également
descendant du nœud courant

Bien que les listes manipulées par XPath peuvent contenir des nœuds et des valeurs
atomiques, ces opérateurs fonctionnent uniquement avec des listes représentant des
ensembles de nœuds. Ils ne fonctionnent pas avec des listes contenant des valeurs
atomiques. Les listes de nœuds retournées par ces opérateurs sont triées dans l'ordre
du document et ne comportent pas de doublon.

6.3. Valeurs atomiques


Bien que XPath traite principalement des nœuds d'un document XML, il lui faut aussi
manipuler des valeurs atomiques afin de sélectionner de façon précise les nœuds. Cette
partie détaille les différents types pour les valeurs atomiques ainsi que les fonctions opérant
sur ces valeurs.

6.3.1. Expressions booléennes

Le type booléen xsd:boolean [Section [Link]] 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

23
not(false())
true

Les valeurs des autres types peuvent être converties explicitement en des valeurs
booléennes par la fonction xsd:boolean() [Section 6.1.6]. Elles sont aussi converties
implicitement dès qu'une valeur booléenne est requise. C'est le cas, par exemple, des filtres
[Section 6.4.2], de la structure de contrôle if [Section 6.6.1] de XPath ou des structures de
contrôle xsl:if [Section 8.7.1] et xsl:when [Section 8.7.2] de XSLT. Les règles qui s'appliquent
alors sont les suivantes.

• Une liste vide est convertie en false.


• Une liste 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 converti 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

6.3.2. Nombres

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
[Section [Link]].

Fonctions sur les nombres

Opérateurs '+', '-' et '*'


Ces opérateurs calculent respectivement la somme, la différence et le produit de deux
nombres entiers, décimaux ou flottants.

24
• 2+3, 2-3, 2*3
5, -1, 6

Opérateur div
Cet opérateur calcule le quotient de la division de deux nombres entiers, décimaux ou
flottants.

• 3 div 2, 4.5 div 6.7


1.5, 0.671641791044776119

Opérateurs idiv et mod


Ces opérateurs calculent respectivement le quotient et le reste de la division entière de
deux entiers.

• 3 idiv 2, 3 mod 2
2, 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

25
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 comparables pour l'ordre lt. Le paramètre
optionnel col spécifie la collation [Section 2.2.5] à utiliser pour comparer des chaînes de
caractères. Les valeurs sans type, c'est-à-dire de type xs:untypedAtomic, sont converties, au
préalable, en flottants par xsd:double() [Section 6.1.6].

• 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 comparables pour l'ordre lt. Le paramètre
optionnel col spécifie la collation à utiliser pour comparer des chaînes de caractères. Les
valeurs sans type, c'est-à-dire de type xs:untypedAtomic, sont converties, au préalable, en
flottants par xsd:double().

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

6.3.3. Chaînes de caractères

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,

26
délimitée par une paire de guillemets, 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 [Chapitre 5] ou XSLT [Chapitre 8]. 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 [Section [Link]] 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 des 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'

27
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
optionnelle 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 conforme à l'expression rationnelle regexp
[Section 5.15] et false sinon. La chaîne optionnelle flags précise comment doit être effectuée
l'opération.

• matches('Hello world', '\w+')


true

• matches('Hello world', '^\w+$')


false

• matches('Hello', '^\w+$')
true

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 s1 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'

28
• 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 translate(xsd:string s, xsd:string from, xsd:string to)


retourne la chaîne obtenue en remplaçant dans la chaîne s chaque caractère de la chaîne
from par le caractère à la même position dans la chaîne to. Si la chaîne from est plus longue
que la chaîne to, les caractères de from sans caractère correspondant dans to sont
supprimés de la chaîne s.

• translate('Hello world', 'lo', 'ru')


'Herru wurrd'

• translate('01-44-27-45-19', '-', '')


'0144274519'

xsd:string replace(xsd:string s, xsd:string regexp, xsd:string repl, xsd:string? flags)


retourne la chaîne obtenue en remplaçant dans la chaîne s les occurrences de
l'expression rationnelle regexp [Section 5.15] 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' où chaque caractère 'o' a été remplacé par le caractère 'u'

• replace('="\&apos;\"=', '(["\\])', '\\$1')


'=\"\\'\\\"=' où un caractère '\' a été inséré devant chaque caractère '"' ou '\'

• replace('(code,1234)', '\(([^,]*),([^\)]*)\)', '($2,$1)')


'(1234,code)' où les textes délimités par '(', ',' et ')' ont été échangés

29
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 [Section 5.15] qui ne peut pas contenir la chaîne vide.

• tokenize('Hello new world', '\s+')


('Hello', 'new', 'world')

• tokenize('Hello&#x20;&#x20;world', '\s')
('Hello', '', 'world')

xsd:string normalize-space(xsd:string s)
supprime les caractères d'espacement [Section 2.2.2] en début et en fin de chaîne et
remplace chaque suite de caractères d'espacement consécutifs par un seul espace. Le
résultat est du type xsd:normalizedString [Section [Link]].

• normalize-space(' Hello &x0A; world ')


'Hello world' où les deux espaces et le retour à la ligne au milieu ont été remplacés par
un seul espace et où les espaces au début et à la fin ont été supprimés

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 points de code [Section 2.2] 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 points de code [Section 2.2].

• string-to-codepoints('A&#8364;0')
(65, 8364, 48)

xsd:string normalize-unicode(xsd:string s, xsd:string? norm)


retourne la normalisation [Section 2.2.6] 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 à
condition que chacune de ces normalisations soit implémentée. Si norm est absente, c'est la
normalisation C (NFC) par défaut qui est utilisée. Celle-ci est toujours implémentée.

30
• normalize-unicode('o&#x308;')
'ö' où le caractère ' ̈' U+308 est le caractère spécial tréma.

6.3.4. Expressions rationnelles

Quelques fonctions XPath comme matches(), replace() et tokenize() prennent en paramètre


une expression rationnelle. La syntaxe de ces expressions est identique à celle des
expressions rationnelles des schémas [Section 5.15] avec seulement quelques différences.

La principale différence avec les expressions rationnelles des schémas est l'ajout des deux
ancres '^' et '$'. Ces deux caractères deviennent spéciaux. Ils désignent la chaîne vide
placée, respectivement, au début et à la fin de la chaîne. Ces deux caractères sont utiles car
la fonction matches() retourne true dès qu'un fragment de la chaîne est conforme à
l'expression rationnelle. Pour forcer la chaîne, prise dans son intégralité, à être conforme, il
faut ajouter les caractères '^' et '$' au début et à la fin de l'expression rationnelle.

• matches('Hello world', '\w+')


donne true car les fragments Hello ou world sont conformes à l'expression \w+.

• matches('Hello world', '^\w+$')


donne false car la chaîne contient un espace.

Le fonctionnement des ancres '^' et '$' est modifié par le modificateur 'm'.

[Link]. Modificateurs

Les fonctions matches() et replace() prennent un dernier paramètre optionnel flag qui
modifie leur comportement. Ce paramètre doit être une chaîne de caractères pouvant
contenir les caractères 'i', 'm' et 's' dans n'importe quel ordre. Chacun de ces caractères joue
le rôle d'un modificateur qui influence un des aspects du fonctionnement de ces fonctions.
Le caractère 'i' indique que la chaîne est comparée à l'expression sans tenir compte de la
casse des lettres. Ceci signifie que les lettres minuscules et majuscules ne sont plus
distinguées.

• matches('Hello world', 'hello')


donne false.

• matches('Hello world', 'hello', 'i')


donne true.

Le caractère 'm' modifie la signification des ancres '^' et '$'. Il indique que la chaîne est
comparée à l'expression en mode multi-ligne. Dans ce mode, la chaîne est vue comme
plusieurs chaînes obtenues en découpant à chaque saut de ligne marqué par le caractère

31
U+0A [Section 2.2.2]. Ceci signifie que le caractère '^' désigne alors la chaîne vide placée au
début de la chaîne ou après un saut de ligne et que le caractère '$' désigne alors
la chaîne vide placée à la fin de la chaîne ou avant un saut de ligne.

• matches('Hello&#xA;world', '^Hello$')
donne false.

• matches('Hello&#xA;world', '^Hello$', 'm')


donne true.

Le caractère 's' modifie la signification du caractère spécial '.'. Il désigne normalement tout
caractère autre qu'un saut de ligne. Avec le modificateur 's', il désigne tout caractère, y
compris le saut de ligne U+0A.

• matches('Hello&#xA;world', '^.*$')
donne false.*

• matches('Hello&#xA;world', '^.*$', 's')


donne true.

6.4. Listes

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).

6.4.1. Constructeurs

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 [Section 6.2], l'opérateur ',' ne réordonne pas les
éléments des listes et ne supprime pas les doublons. Le résultat de l'expression expr1,expr2
est la nouvelle liste formée des valeurs du résultat de expr1 suivies des valeurs du résultat
de 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,3) est bien
la liste (1,2,1,3) avec deux occurrences de l'entier 1.

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.

32
title, author
donne la liste des enfants de nom title puis des enfants de nom author du nœud courant.

1, 'Two', 3.14, true()


donne la liste (1, 'Two', 3.14, true) constituée d'un entier, d'une chaîne de caractères, d'un
nombre flottant et d'une valeur booléenne.

(1, 2), 3, (4, (5))


donne la liste (1, 2, 3, 4, 5) sans imbrication.

(1, 2), 2, 1, 2
donne la liste (1, 2, 2, 1, 2) avec répétitions.

L'opérateur to permet de créer une liste contenant une suite d'entiers consécutifs.
L'expression n1 to n2 donne la liste n1,n1+1,n1+2,...,n2-1,n2 des entiers de n1 à n2
compris. Cet opérateur est surtout utile avec l'opérateur for [Section 6.6.2] pour itérer sur
une liste d'entiers.

1 to 5
donne la liste (1, 2, 3, 4, 5)

1, 2 to 4, 5
donne la liste (1, 2, 3, 4, 5)

6.4.2. Filtres

Un filtre permet d'extraire d'une liste les objets qui satisfont une condition pour former une
nouvelle liste. Un filtre se présente comme une expression entre des crochets '[' et ']' placée
après la liste à filtrer.

Une expression de la forme expr1[expr2] est évaluée de la façon suivante. L'expression


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 [Section [Link]] 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 [Section 6.3.1]. Le résultat final de l'évaluation de expr1[expr2] est la liste des
objets de 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 courant 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]
donne la liste (2,4) des entiers pairs de la liste

33
Les filtres sont beaucoup utilisés dans les expression de chemin [Section 6.2.2] 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]


donne les enfants text du nœud courant aux positions 2 et 3

text[position() > 1][position() < 4]


donne 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é.

Les expressions de chemins retournent des listes de nœuds triés dans l'ordre du document
et sans doublon. Au contraire, l'opérateur ',' ne supprime pas les doublons.

p[@align or @type]
donne la liste des enfants p du nœud courant ayant un attribut align ou type.

p[@align], p[@type]
donne la liste des enfants p du nœud courant ayant un attribut align suivis des enfants p
ayant un attribut type. Si un nœud p possède les deux attributs, il apparaît deux fois dans la
liste.

6.4.3. Fonctions

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

34
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
éventuellement 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)

item()* reverse(item()* l)
retourne la liste obtenue en inversant l'ordre

• reverse(1 to 5)
(5, 4, 3, 2, 1)

35
6.5. Comparaisons

Les comparaisons sont un aspect important mais délicat de XPath. 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 délicates à
utiliser car leur sémantique n'est pas toujours intuitive.

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. Ils nécessitent, en
revanche, que les valeurs comparées soient du bon type. Ceci impose de valider le
document avec un schéma ou de faire des conversions explicites de types avec les
fonctions appropriées [Section 6.1.6].

Il existe aussi l'opérateur is et les deux opérateurs << et >> permettant de tester l'égalité et
l'ordre des nœuds [Section 6.1.2] dans le document.

6.5.1. Opérateurs de comparaisons atomiques

Les opérateurs de comparaison 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 3
donne true

2 lt 3
donne true

'chaine' ne 'string'
donne true

'chaine' lt 'string'
donne true

36
Ces opérateurs de comparaison exigent que leurs deux paramètres soient du même type.
Les constantes présentes dans le programme sont automatiquement du bon type. En
revanche, les contenus des éléments et les valeurs des attibuts doivent être convertis
explicitement à l'aide des fonctions de conversion lorsque le document est traité
indépendamment d'un schéma. Pour tester si la valeur d'un attribut pos vaut la valeur 1, il
est nécessaire d'écrire xsd:integer(@pos) eq 1 où la valeur de l'attribut pos est convertie en
entier par la fonction xsd:integer. Les opérateurs généraux de comparaison évitent ces
conversions fastidieuses car ils effectuent eux-mêmes des conversions implicites.

La contrainte d'égalité des types des valeurs n'est pas stricte. Il est possible de comparer
une valeur d'un type avec une valeur d'un type obtenu par restriction [Section 5.9]. Il est
également possible de comparer des valeurs des différents types numériques xsd:integer,
xsd:decimal, xsd:float et xsd:double.

6.5.2. Opérateurs généraux de comparaisons

Les opérateurs généraux de comparaison 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.

Les objets à comparer sont d'abord atomisés [Section [Link]], ce qui signifie que les nœuds
présents dans les listes sont remplacés par leur valeur pour obtenir uniquement des valeurs
atomiques. Ensuite, la comparaison est effectuée de façons différentes suivant que les
objets sont des listes composées d'une seule valeur (considérées alors comme une simple
valeur) ou de plusieurs valeurs.

[Link]. Comparaisons de valeurs atomiques

La façon de réaliser une comparaison entre deux valeurs atomiques dépend du type
[Section 6.1.4] de ces deux valeurs. Suivant les types de celles-ci, certaines conversions
sont effectuées au préalable puis elles sont comparées avec l'opérateur de comparaison
atomique correspondant donné par la table suivante.

37
Lorsque les deux valeurs sont de type xsd:untypedAtomic, celle-ci sont comparées comme
des chaînes de caractères. Lorsqu'une seule des deux valeurs est de type
xsd:untypedAtomic, celle-ci est convertie dans le type de l'autre valeur avant de les
comparer. Quand le type de l'autre valeur est un type numérique, la valeur de type
xsd:untypedAtomic est convertie en une valeur de type xsd:double plutôt que dans le type
de l'autre valeur. Ceci évite qu'une valeur décimale comme 1.2 soit convertie en entier avant
d'être comparée à la valeur 1. Si les deux valeurs sont de types incompatibles, la
comparaison échoue et provoque une erreur.

Pour illustrer ces comparaisons, on considère le petit document suivant.

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>


<list>
<item type="1">1</item>
<item type="01">2</item>
<item type="03">3</item>
<item type="1.2">4</item>
<!-- Erreur car 'str' ne peut être convertie en nombre flottant -->
<item type="str">5</item>
</list>

Les expressions suivantes sont évaluées sur le document précédent en supposant, à


chaque fois, que le nœud courant est l'élément racine list du document. Pour chacune des
expressions, le résultat est une liste d'enfants item de l'élément list. Il est décrit en donnant
les positions de ces éléments item sélectionnés. Le résultat item[1], item[2] de la première
expression signifie, par exemple, qu'elle sélectionne le premier et le deuxième enfants item.

item[@type=1]
donne item[1], item[2] car la valeur de l'attribut type est convertie en nombre flottant avant
d'être comparée à 1. La valeur '01' est donc convertie en '1'.

item[@type='1']
donne item[1] car la valeur de l'attribut type est convertie en chaîne de caractères avant
d'être comparée à '1'.

item[@type=.]
donne item[1] car la valeur de l'attribut type et le contenu de l'élément item sont convertis
en chaînes de caractères avant d'être comparés.

item[@type=1.2]
donne item[4] car la valeur de l'attribut type est convertie en nombre flottant avant d'être
comparée à 1.2.

item[xsd:double(.)=xsd:double(@type)]
donne item[1], item[3] car la valeur de l'attribut type et le contenu de l'élément item sont
convertis en nombres flottants avant d'être comparés.

38
Il faut faire attention au fait que les comparaisons peuvent échouer et provoquer des erreurs
lorsque les types ne sont pas compatibles. Ce problème renforce l'intérêt de la validation
des documents avant de les traiter.

[Link]. Comparaisons de listes

Les comparaisons entre listes ont une sémantique très particulière qui est parfois pratique
mais souvent contraire à l'intuition. Ce cas s'applique dès qu'un des deux objets comparés
est une liste puisqu'une valeur est identifiée à une liste de longueur 1. La comparaison entre
deux listes l1 et l2 pour un des opérateurs =, !=, <, <=, > et >= est effectuée de la façon
suivante. Chaque valeur de la liste l1 est comparée avec chaque valeur de la liste l2
pour le même opérateur, comme décrit à la section précédente. Le résultat global est égal à
true dès qu'au moins une des comparaisons donne la valeur true. Il est égal à false sinon.
Cette stratégie implique en particulier que le résultat est false dès qu'une des deux listes est
vide quel que soit l'opérateur de comparaison.

() = ()
donne false car une des deux listes est vide.

() != ()
donne false car une des deux listes est vide.

L'exemple précédent montre que l'opérateur != n'est pas la négation de l'opérateur =, ce qui
n'est pas très intuitif.

() != (1)
donne false car une des deux listes est vide.

(1) = (1)
donne true car la valeur 1 de la liste l1 est égale à la valeur 1 de la liste l2.

(1) != (1)
donne false car l'unique valeur 1 de la liste l1 n'est pas différente de l'unique valeur 1 de
la liste l2.

(1) = (1, 2)
donne true car la valeur 1 de la liste l1 est égale à la valeur 1 de la liste l2.

(1) != (1, 2)
donne true car la valeur 1 de la liste l1 est n'est pas égale à la valeur 2 de la liste l2.

Dès que la comparaison de deux valeurs des listes l1 et l2 échoue, la comparaison globale
entre les listes l1 et l2 échoue également. L'ordre des comparaisons entre les valeurs des
deux listes est laissé libre par XPath et chaque logiciel peut les effectuer dans l'ordre qui lui
convient. Lorsqu'une de ces comparaisons donne la valeur true et qu'une autre de ces
comparaisons échoue, le résultat de la comparaison des deux listes est imprévisible.

39
Il est égal à true si une comparaison donnant true est effectuée avant toute comparaison qui
échoue mais la comparaison globale échoue dans le cas contraire.

La sémantique des comparaisons de listes permet d'écrire simplement certains tests. Pour
savoir si une valeur contenue, par exemple, dans une variable $n est égale à une des
valeurs de la liste (2, 3, 5, 7), il suffit d'écrire $n = (2, 3, 5, 7).

6.5.3. Opérateurs de comparaisons de nœuds

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érateur '==' de Java qu'à la
méthode equals du même langage.

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 [Section 6.1.2].

Pour illustrer ces trois opérateurs, on considère le document minimaliste suivant.

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>


<list length="2">
<item type="1">1</item>
<item type="1">2</item>
</list>

Les expressions suivantes sont évaluées sur le document précédent en supposant, à


chaque fois, que le nœud courant est la racine du document.

list is list/item/parent::*
donne true car il s'agit du même nœud qui est l'élément racine du document.

list/item[1]/@type is list/item[2]/@type
donne false car il s'agit de deux nœuds différents bien que les deux attributs aient même
nom et même valeur.

list << list/item[1]


donne true car le père est placé avant ses enfants dans l'ordre du document.

list/@length << list/item[1]


donne true car les attributs sont placés avant les éléments enfants.

list/item[1] << list/item[2]


donne true.

Un exemple pertinent d'utilisation de l'opérateur is est donné par la feuille de style avec
indexation pour regrouper les éditeurs et supprimer leurs doublons dans le document
[Link].

40
6.6. Structures de contrôle

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 [Chapitre 8] suivant avec un test dans
l'expression XPath. Dans l'exemple suivant, l'élément a contient une expression XPath en
attribut dont le résultat devient la valeur de son attribut id. Cette expression retourne la
valeur de l'attribut xml:id de l'élément courant si cet attribut existe ou génère un nouvel
identifiant sinon.

<a id="{if (@xml:id) then @xml:id else generate-id()}"/>

Elle est équivalente au fragment XSLT suivant où le test est réalisé par un élément
xsl:choose.

<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>

6.6.1. Conditionnelle

L'opérateur if permet d'effectuer un test. Sa syntaxe est la suivante.

if (test) then expr1 else expr2

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 [Section 6.3.1]. 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 expr2 est obligatoire et ne peut pas être omise. Lorsque cette seconde partie
est inutile, on met simplement else ().

if (contains($url, ':')) then substring-before($url, ':') else ''


l'évaluation de cette expression retourne le protocole d'une URL [Section 2.3] placé avant
le caractère ':' si celle-ci en contient un.

41
L'opérateur if est parfois remplacé par un filtre [Section 6.4.2]. L'expression if (@xml:id) then
@xml:id else generate-id() est en effet équivalente à l'expression plus concise (@xml:id,
generate-id()) [1].

6.6.2. Itération

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 ou le while
des langages C ou Java. Il s'apparente plus à l'opérateur map des langages fonctionnels
comme ML qui permet d'appliquer une fonction à chacun des objets d'une liste.

La syntaxe de l'opérateur for est la suivante où var est une variable et expr1 et expr2 sont
deux expressions. La variable var peut uniquement apparaître dans l'expression expr2.

for var in expr1 return expr2

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 * $i
l'é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 * $i


l'é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.

42
for var-1 in expr-1, ..., var-N in expr-N return expr

Cette expression est, en fait, équivalente à l'expression suivante écrite avec la première
syntaxe.

for var-1 in expr-1 return for … return for var-N in expr-N return expr

for $i in 0 to 2, $j in 0 to 2 return $i * 3 + $j
l'é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)

6.6.3. Quantification existentielle

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.

some var in expr1 satisfies expr2

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 [Section 6.3.1]. Il est égal à false sinon.

some $i in 0 to 5 satisfies $i > 4


l'évaluation de cette expression donne la valeur true car la condition $i > 4 est satisfaite
pour $i = 5

6.6.4. Quantification universelle

L'opérateur every permet de vérifier que tous les objets d'une liste satisfont une condition.
Sa syntaxe est la suivante.

every var in expr1 satisfies expr2

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 [Section 6.3.1]. Il est égal à false sinon.

every $i in 0 to 5 satisfies $i > 4


l'é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 5


l'évaluation de cette expression donne la valeur true

43
6.7. Syntaxe abrégée

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.

Il faut remarquer que '//' n'est pas une abbréviation de descendant-or-self::. Les deux
expressions //section[1] et descendant-or-self::section[1] donnent des résultats différents. La
première expression donne la liste des éléments section qui sont le premier enfant section
de leur parent alors que la seconde donne le premier élément section du document.

6.8. Motifs

Les motifs XPath sont des expressions XPath simplifiées permettant de sélectionner de
façon simple des nœuds dans un document. Ils sont beaucoup utilisés par XSLT, d'abord
pour spécifier des nœuds auxquels s'applique une règle [Section 8.5.1] mais aussi pour la
numérotation et l'indexation. Ils répondent à une exigence d'efficacité. Le cœur de XSLT est
l'application de règles à des nœuds du document source. Il est important de déterminer
rapidement quelles sont les règles susceptibles de s'appliquer à un nœud. Dans ce but, les
motifs n'utilisent qu'un sous-ensemble très limité de XPath. De surcroît, les motifs sont
évalués de façon particulière, sans utiliser le nœud courant.

Les seuls opérateurs utilisés dans les motifs sont les opérateurs '|', '/' et '//' et leur imbrication
est très restreinte. Un motif prend nécessairement la forme suivante

expr-1 | expr-2 | ... | expr-N

44
où les expressions expr-1, ..., expr-N ne contiennent que des opérateurs '/' et '//'. En outre,
les seuls axes possibles dans les motifs sont les deux axes child::, attribute::. L'axe
descendant-or-self:: est implicite dans l'utilisation de l'opérateur '//' mais c'est la seule façon
de l'utiliser dans un motif. En revanche, les tests portant sur les types de nœuds comme
text() ou comment() et les filtres sont autorisés dans les motifs.

L'évaluation d'un motif XPath est réalisée de façon différente d'une expression XPath
classique. Celle-ci ne nécessite pas de nœud courant. Un motif est toujours évalué à partir
de la racine du document. De plus, un motif commence toujours implicitement par
l'opérateur '//'. Le motif section est, en fait, évalué comme l'expression //section. Il
sélectionne tous les éléments section du document. Des exemples de motifs avec
les nœuds qu'ils sélectionnent sont donnés ci-dessous.

/
la racine du document

*
tous les éléments

section
tous les éléments section

chapter|section
tous les éléments chapter et section

chapter/section
tous les éléments section enfants d'un élément chapter

chapter//section
tous les éléments section descendants d'un élément chapter

section[1]
tous les éléments section qui sont le premier enfant de leur parent

section[@lang]
tous les éléments section ayant un attribut lang

section[@lang='fr']
tous les éléments section dont l'attribut lang a la valeur fr

@*
tous les attributs

section/@lang
tous les attributs lang des éléments section

text()
tous les nœuds textuels

45
6.9. Utilisation interactive de xmllint

Le logiciel xmllint possède un mode interactif avec lequel il est possible de se déplacer dans
un document XML comme s'il s'agissait d'un système de fichiers. Les nœuds du documents
XML sont assimilés à des répertoires (dossiers) et fichiers. Ce mode interactif s'apparente à
un interpréteur de commandes (shell) dont le répertoire de travail devient le nœud courant.
Les commandes permettent de se déplacer dans le document en changeant le nœud
courant et en évaluant des expressions XPath par rapport à ce nœud courant. L'intérêt de ce
mode interactif réside bien sûr dans la possibilité d'expérimenter facilement les expressions
XPath.

Le mode interactif de xmllint est activé avec l'option --shell. Les principales commandes
disponibles sont alors les suivantes.

help
affiche un récapitulatif des commandes disponibles.

cd path
change le nœud courant en le nœud retourné par l'expression XPath path.

pwd
affiche le nœud courant.

xpath path
affiche le résultat de l'évalution de l'expression XPath path.

cat [node]
affiche le contenu du nœud node.

dir [node]
affiche les informations relatives au nœud node.

grep string
affiche les occurrences de la chaîne string dans le contenu du nœud courant.

Une session d'expérimentation du mode interactif de xmllint avec le fichier de bibliographie


[Link] est présentée ci-dessous.

bash $ xmllint --shell [Link]


/ > grep XML
/bibliography/book[1]/title : t-- 27 XML langage et applications
/bibliography/book[2]/title : t-- 14 XML by Example
/bibliography/book[5]/title : t-- 46 Modélisation et manipulation ...
/bibliography/book[6]/title : t-- 25 XML Schema et XML Infoset
/bibliography/book[7]/title : ta- 3 XML
/ > xpath bibliography/book[@lang='en']

46
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 >

6.10. Récapitulatif des opérateurs XPath

47
48

Vous aimerez peut-être aussi