From: Kim Nguyễn Date: Mon, 22 Sep 2014 20:26:01 +0000 (+0200) Subject: Add XPI lecture 3 X-Git-Url: http://git.nguyen.vg/gitweb/?p=hacks%2FsimpleWebSlides.git;a=commitdiff_plain;h=db35e40feec7ef37f162d4771e9523ab33843565 Add XPI lecture 3 --- diff --git a/xpi/pdf/xpi_03.pdf b/xpi/pdf/xpi_03.pdf new file mode 100644 index 0000000..5584f20 Binary files /dev/null and b/xpi/pdf/xpi_03.pdf differ diff --git a/xpi/pdf/xpi_03_print.pdf b/xpi/pdf/xpi_03_print.pdf new file mode 100644 index 0000000..8886900 Binary files /dev/null and b/xpi/pdf/xpi_03_print.pdf differ diff --git a/xpi/xpi_03.xhtml b/xpi/xpi_03.xhtml new file mode 100644 index 0000000..2e5d601 --- /dev/null +++ b/xpi/xpi_03.xhtml @@ -0,0 +1,440 @@ + + + + + XPath (suite) + + + + + + + + + + + + + + + + + + + + +
+

XML et Programmation Internet

+

Cours 3

+
kn@lri.fr +
+

Évaluation des prédicats

+
+

Rappels de syntaxe

+ + p ::= p or p + | p and p + | not (p) + | count(…), contains(…), position(), … + | chemin XPath + | e1 op e2 + +

On évalue le prédicat et on converti son résultat en valeur de + vérité. Si la valeur vaut vrai, on garde le nœud courant, si elle + vaut faux, on ne le garde pas +

+

XPath connait 4 types de données pour les prédicats :

+ +
+
+

Comparaisons (e1 op e2)

+

Les opérateurs de comparaisons sont : =, !=, <, <=, + >, >= .
+ La manière de calculer de vérité de e1 op + e2 dépend du typed de e1 + et e2 : +

+ +
+
+

Comparaisons des valeurs scalaires

+ v1 op v2 +

Si op est != ou =, on applique les règles dans cet ordre:

+
    +
  1. Si v1 (resp. v2) est + un booléen, alors v2 + (resp. v1) est converti en booléen et les deux + booléens sont comparés
  2. +
  3. Sinon si v1 (resp. v2) est + un nombre, alors v2 + (resp. v1) est converti en nombre et les deux + nombres sont comparés
  4. +
  5. Sinon, v1 et v2 sont des + chaines de caractères, on les compares
  6. +
+

Si op est <, <=, > ou + >=, on convertit v1 + et v2 en nombres et on les compare. +

+
+
+

Conversions

+

Conversion en booléen

+ +

Conversion en nombre

+ +
+
+

Conversions (suite)

+

Conversion en chaine de caractères

+ +
+ +
+

Appels de fonction

+

Il existe des fonctions prédéfinies (voir la spec XPath)

+ +

Si les arguments ne sont pas du bon type, ils sont convertis en + utilisant les règles de conversion

+
+
+

Exemples

+

Dans la suite, on se donne un document de test ayant une + racine ... ]]> et une expression XPath qui + sélectionne la racine si et seulement si le prédicat vaut vrai +

+
+
+

Exemples

+ + 1 + 2 + ]]> +
  1. + /child::a[ child::*/child::text() ] + sélectionne la racine (l'ensemble de nœud + renvoyé par child::*/cild::text() est non vide, donc il est converti + en true)

  2. +
  3. + /child::a[ child::*/child::text() = "2" ] + sélectionne la racine (l'ensemble de nœud texte + renvoyé par child::*/child::text() est comparé à "2", et + il existe un élément dans cet ensemble pour lequel le test réussi + )

  4. +
  5. /child::a[ child::*/child::text() != "2" ] + sélectionne la racine (l'ensemble de nœud texte + renvoyé par child::*/child::text() est comparé à "2", et + il existe un élément dans cet ensemble pour lequel le test réussi + )

  6. +
  7. /child::a[ not(child::*/child::text() = "2") ] + ne sélectionne pas la racine (on + prend la négation du deuxième cas ci-dessus) +

  8. + +
+
+
+

Exemples

+ + 12 + 23 + ]]> +
    +
  1. + /child::a[ child::*/child::text() > 1.5 ] + sélectionne la racine (l'ensemble de nœud texte + renvoyé par child::*/child::text() est comparé à 1.5, et + il existe un élément dans cet ensemble pour lequel le test réussi + )

  2. +
  3. /child::a[ child::b/child::text() >= child::c/child::text() ] + sélectionne la racine (les deux + ensembles de nœuds sont convertis en ensmbles de nombres, car on + utilise >= et on a bien que 2 >= 2 + )

  4. +
  5. /child::a[ child::b/child::text() = child::c/child::text() ] + sélectionne la racine (les deux + ensembles de nœuds comportent un élément commun)

  6. +
  7. /child::a[ child::b/child::text() != child::c/child::text() ] + sélectionne la racine (les deux + comportent des éléments différents)

  8. +
+
+
+

Exemples

+ 1223 ]]> +
    +
  1. + /child::a[ contains(self::*, "22") ] + sélectionne la racine(l'ensemble de + nœud séléctionné par self::*, i.e. la racine est converti + en chaine. Pour ce faire, on colle toutes éléments textes + descendants et on obtient la chaine "1223" qui contient bien "22") +

  2. +
  3. + /child::a[ self::* > 442.38 ] + sélectionne la racine(l'ensemble de + nœud séléctionné par self::*, est converti en chaine puis + en nombre pour comparer 1223 à 442.38) +

  4. + +
  5. + /child::a[ sum(child::*) >= 7.5 ] + sélectionne la racine(la fonction + sum converti la liste de valeurs passée en argument en + liste de nombre et fait la somme de ces derniers) +

  6. +
+
+ +
+

Exemples

+ 1toto23 ]]> +
    + +
  1. + /child::a[ sum(child::*) >= 7.5 ] + ne sélectionne pas la racine(la fonction + sum converti la liste de valeurs passée en argument en + liste de nombres, toto n'étant pas un nombre valide, il est + remplacé par NaN. La somme totale fait donc NaN, et une + comparaison avec NaN renvoie toujours faux) +

  2. +
+
+
+

Prédicat imbriqués

+

On peut imbriquer des prédicats de manière arbitraire:

+ Q1 ≡ /child::a[ child::b[ count(descendant::c) > 4 ] ] +

Quelle différence avec :

+ Q2 ≡ /child::a[ count(child::b/descendant::c) > 4 ] +

Il suffit de considérer le document : + + + + + ]]> + Q1 ne séléctionne rien car il n'y a + aucun b ayant plus de 4 + descendants c.
Q2 séléctionne + la racine car le nombre de descendants c de + nœuds b est plus grand que 4. +

+
+
+

position() et last()

+

La fonction position() renvoie la position du nœud au + sein de l'ensemble de résultats en cours de filtrage. Last + renvoie le nombre d'éléments dans cet ensemble (ou l'indice du + dernier élément). Les indices commencent à 1 :

+ + AA + BB + CC + ]]> + + /child::a/child::b[ position() = 2 ] (renvoie BB]]>) + /child::a/child::b[ position() = last() ] (renvoie CC]]>) + /child::a/child::b[ position() mod 2 = 1 ] (renvoie AA + CC]]>) + +
+

Axes complexes

+
+

L'axe attribute::

+

Permet d'accéder aux attributs d'un élément.Attention, les + attributs ne font pas partie des fils ni des descendants!

+ + AA + BB + CC + ]]> + + /descendant::b[ attribute::* = "y" ] (renvoie BB]]>) + /descendant::b[ attribute::id = "y" ] (ne renvoie rien) + +
+
+

Les axes preceding:: et following::

+

L'axe preceding:: selectionne tous les nœuds arrivant + avant le nœud courant et qui ne sont pas des ancetres de ce + dernier.

+

L'axe following:: selectionne tous les nœuds arrivant + après le nœud courant et qui ne sont pas des descendants de ce dernier.

+ + + + + + + + + + + + ]]> + + /descendant::m/preceding::* (séléctionne l, i, h, b, c, d, e, f, g) + /descendant::d/following::* (sélectionne h, i, j, k, l, m) + +
+
+

Autres opérateurs

+

On peut donner plusieurs prédicats à un chemin : + + /descendant::a [ descendant::b ][ position () > 4 ][ child::c ] + +Sélectionne l'ensemble des nœuds A1 ayant un + tag a et ayant un descendant b. Filtre + A1 pour ne garder que A2, l'ensemble des + nœuds de A1 étant en position supérieure à + 4. Filtre A2 pour ne + garder que les nœuds ayant un fils c. +

+

On peut prendre l'union de plusieurs chemins :

+ + /descendant::a/parent::b | /descendant::c/following-sibling::d + +
+

Syntaxe abrégée

+
+

Abréviations

+

XPath étant très verbeux il existe une syntaxe abrégée pour + les situations les plus courantes :

+
    +
  • un nom de tag foo est l'abréviation + de child::foo. Exemple : /a/b/c ≡ /child::a/child::b/child::c +
  • +
  • un // est l'abréviation + de /descendant-or-self::node()/. Exemple : + //a ≡ /descendant-or-self::node()/child::a + Prend tous les nœuds du document (y compris le + nœud fictif #document et exécute child::a sur + cet ensemble.
  • +
  • .. est un synonyme + pour parent::node()
  • +
  • @foo est un synonyme pour attribute::foo +
  • +
+

Exemple :

+ //book [ year > 2005 ]/title + + +
+ +