• Aucun résultat trouvé

2.4 Le langage XPath

2.4.6 Types et opérations XPath

XPath fournit un support limité pour effectuer des opérations ou des comparaisons sur des nombres ou des chaînes de caractères. Ces opérations ou comparaisons impliquent le plus souvent un typage de certaines parties d’un document XML. On peut les utiliser pour les prédicats, afin de tester des valeurs numériques par exemple, mais aussi avec XSLT quand on chercher à produire un résultat calculé à partir des informa- tions du document source. On peut vouloir par exemple prendre des sous-chaînes, effectuer des calculs arithmétiques, etc.

XPath connaît quatre types de données :

1. les numériques utilisent la notation décimale habituelle, avec un point pour les flottants (10.5) et un signe moins (-) devant les nombres négatifs (-10) ;

2. les chaînes de caractères sont constituées d’une suite de caractères reconnus par le codage du docu- ment, et délimitées par des guillemets (") ou des apostrophes (’) : attention les blancs sont significatifs (“azerty” est différent de “ azerty “) ;

3. les booléens correspondent aux valeurs habituellestrueetfalse;

4. enfin les ensembles de nœuds sont un sous-ensemble, sans doublon, des nœuds du document source. Les comparateurs usuels (F , E , !=, =,F+L , E+L ) peuvent être utilisés pour tous les types scalaires (numériques, chaînes et booléens). Pour les opérations on peut avoir besoin d’effectuer une conversion d’un type à un autre. Ces conversions peuvent être soit implicites, quand l’expression indique clairement que l’une des opérandes appartient à un type donné, soit explicites avec les fonctions number(), boolean() et string().

Il faut bien noter qu’un document XML est essentiellement une chaîne de caractères structurée par des balises, et n’est donc pas typé, comme peut l’être un programme écrit dans un langage comme Java ou C++, chaque variable y étant déclarée comme appartenant à un certain type. Il ne peut donc y avoir de garantie que le résultat d’une expression XPath puisse être converti dans le type attendu, et ce même si le document est valide (conforme à une DTD). Cependant toute expression peut être convertie (« interprétée ») soit comme un booléen, soit comme une chaîne, ce qui est particulièrement important pour les raisons suivantes :

1. les tests effectués dans XSLT (xsl:if,xsl:when) peuvent prendre n’importe quelle expression, l’évaluer, et considérer le résultat commetrueoufalse;

2. la production de texte en XSLT (balisexsl:value-of) doit convertir le résultat d’une expression XPath en chaîne de caractères pour l’incorporer au document résultat.

La compréhension des principales règles de typage, d’évaluation d’expressions typées et de conversions d’un type à un autre ci-dessous est donc essentielle. Nous ne donnons pas en revanche dans ce chapitre la liste complète des fonctions XPath qui figure dans l’annexe B

Opérateurs Syntaxe et description + Addition :n1+n2

- Soustraction : n1-n2. Attention à laisser un blanc de chaque côté du ’-’, sinon le signe est interprété comme faisant partie de n1oun2.

M

Multiplication :n1*n2

div Division :n1divn2(laisser un blanc de chaque côté)

mod Reste de la division : n1 modn2(laisser un blanc de chaque côté)

Table 2.17: Opérateurs numériques

Les numériques

Les opérateurs sur les types numériques sont donnés dans le tableau 2.17. La valeur numérique d’un nœud est obtenue en lui appliquant la fonction number() qui fonctionne de la manière suivante :

5

élimination des blancs avant le premier caractère et après le dernier caractère ;

5

recherche du signe ’-’ ;

5

interprétation de la chaîne restante comme un numérique.

Si la conversion est impossible, la fonction renvoieNaN(« Not a Number »). Voici par exemple une expression XPath qui recherche tous les nœuds ayant un attribut dont la valeur est impaire.

//node()[number(@att1) mod 2 = 1]

Sur notre exemple de référence, on obtiendrait le nœudC(figure 2.33).

Document - Instruction Java ins1 Element A Element B Attr att1 a1 Element D Text - Texte1 Element D Text - Texte2 Element B Attr att1 a2 Element D Text - Texte3 Element C Attr att2 a3 Attr att3 15 Comment - CommFin

Figure 2.33: Résultat de //node()[number(@att1) mod 2 = 1]

Pour tous les nœuds ayant un attribut dont la valeur est une chaîne de caractères qui ne peut être convertie vers un numérique, le résultat de la fonction estNaN,

Les comparaisons avec unNaNdonnent des résultats assez étranges. Un test d’égalité renvoiefalse si l’une des opérandes estNaN. En revanche un test d’inégalité (« != ») renvoie toujourstruequand une des opérandes estNaN. Voici quelques conséquences que nous vous laissons méditer :

2.4. LE LANGAGE XPATH 105 1. NaN = NaNvautfalse;

2. NaN != NaNvauttrue;

3. number(X) != number(X)vauttruesiXn’est pas un nombre !

Nous voici donc dotés d’un bon moyen de rendre des expressions incompréhensibles. Ce n’est pas le dernier.

Les booléens

Les booléens prennent deux valeurs, trueet false, que l’on peut explicitement introduire dans les expressions avec les fonctions true() et false(). Toutes les chaînes avec au moins un caractère, ainsi que tous les numériques non nuls, sont assimilés à la valeur booléennetrue; les chaînes vides, la valeur 0 ouNaNsont assimilés àfalse. Ces règles permettent d’interpréter (en se donnant un peu de mal) les conversions effectuées depuis une valeur de type numérique ou chaîne de caractères vers un booléen, soit implicitement, soit avec la fonction boolean().

La conversion d’un booléen vers un autre type scalaire s’effectue selon les règles suivantes :

5

Vers un numérique (fonction number()) : on obtient 1 avectrue, et 0 avecfalse.

5

Vers une chaîne (fonction string()) : on obtient la chaînefalseou la chaînetrue. Voici quelques exemples :

1. boolean(’azerty’) = true 2. boolean(’0’) = true 3. boolean(0) = false 4. number (1 = 0) = 0 5. number (1 = 1) = 1 6. string (1 = 1) = ’true’

Les choses se compliquent un peu plus quand on doit effectuer une comparaison entre un booléen et une autre valeur, et notamment quand la conversion des deux opérandes est nécessaire pour les ramener toutes deux au même type. Voici les règles de base :

1. quand l’opérateur est « = » ou « != » (comparison operator) la valeur non booléenne est convertie en booléen ;

2. pour les autres opérateurs, on tient compte du type de l’opérande non booléenne : (a) si c’est un numérique, on convertit le booléen en numérique (donc 0 ou 1) ; (b) si c’est une chaîne, on convertit les deux opérandes en numérique.

Voici quelques exemples :

1. true() = 5: on convertit 5 en booléen, ce qui donnetrue, et le résultat de la comparaison est true;

2. true() E 5: on convertit le booléentrueen numérique, ce qui donne 1, et le résultat de la comparaison estfalse;

3. true() != ’azerty’: on convertitazertyen booléen, ce qui donnetrue, et le résultat de la comparaison estfalse;

4. false() E ’azerty’: on convertit le booléenfalseen numérique, ce qui donne 0, ainsi que azerty, ce qui donne 1, et le résultat de la comparaison estfalse;

Ensembles de nœuds

Étudions pour finir le cas des ensembles de nœuds. Notons tout d’abord qu’il est impossible de convertir un type scalaire vers un ensemble de nœuds, ce qui divise par deux le problème : les conversions seront toujours appliquées à un ensemble pour le transformer vers un type scalaire.

La conversion la plus courante s’effectue vers une chaîne de caractères. Voici tout d’abord les règles donnant une valeur textuelle pour chaque type de nœud d’un arbre XPath :

5

pour un nœud de type Text, on obtient directement le contenu du nœud ;

5

pour un nœud de type Comment, on obtient toute la chaîne comprise entre ’F !--’ et ’--E ’ ;

5

pour un nœud de type ProcessingInstruction, on obtient toute la chaîne comprise entre le nom (ou « cible ») de l’instruction et ’?E ’ ;

5

pour un nœud de type Attr, on obtient la valeur de l’attribut ;

5

enfin pour un nœud de type Element ou de type Document, le contenu textuel est la concaténation de tous les contenus des descendants du nœud qui sont de type Text.

Par exemple, en reprenant encore une fois notre exemple de référence, le contenu de l’élément/Aest la concaténation deTexte1,Texte2etTexte3; le contenu de l’élément/A/B[1]5est la concaténation deTexte1,Texte2, etc.

On peut maintenant définir comme suit les conversions d’un ensemble de nœuds vers les types scalaires : 1. vers une chaîne de caractères : c’est le contenu textuel du nœud de l’ensemble qui apparaît en

première position dans l’ordre du document.

2. vers un numérique : on convertit d’abord en chaîne, puis on convertit la chaîne avec number() ; 3. vers un booléen : la conversion booléenne d’un ensemble de nœuds donnetruesi l’ensemble n’est

pas vide,falsesinon.

Le tableau 2.18 résume les règles de conversion que nous avons vues jusqu’ici.

De/Vers Booléen Numérique Chaîne Ensemble de nœuds

Booléen – false N 0 ; trueN 1 false N ’false’ ; trueN ’true’ Interdit Numérique O et NaN N false; sinon true

– format décimal Interdit

Chaîne si videN false;

sinontrue

conversion vers nombre

– Interdit

Ensemble de nœuds si videN false;

sinontrue

conversion chaîne puis nombre

contenu du premier nœud dans l’ordre du document

Table 2.18: Conversions de types XPath

Il est maintenant possible d’effectuer des comparaisons entre un ensemble de nœuds et une instance de n’importe quel autre type XPath. Voici les règles à appliquer à un ensemble de nœuds dénotéO :

1. pour comparerO et une chaîneP , on convertit tous les nœuds de O vers leurs valeurs textuelles ; si une seule de ces valeurs est égale àP la comparaison renvoietrue, etfalsesinon ;

2. pour comparer O et un nombre Q , on effectue comme précédemment une conversion de chaque nœuds vers une valeur numérique, et on compare avecQ ;

2.4. LE LANGAGE XPATH 107 3. pour une comparaison avec une valeur booléenne, on prend simplement la conversion deO vers un

booléen ;

4. enfin pour comparerO avec un second ensembleORJ , on prend les valeurs textuelles des nœuds de O et de ORJ et on les compare deux à deux : si on obtienttruepour au moins une paire, alors la comparaison globale renvoietrueégalement.