P
'
t
i
t
e
C
h
a
t
t
e
 
spacer~ CONFUCIUS SAY: MAN WHO DROP WATCH IN TOILET HAVE S**TTY TIME Articles | Connexion
 
~XPath

 Présentation

La nature structurelle des documents XML se révèle propice à l'emploi d'un langage de requêtes pour dénicher un ou des éléments de l'arbre. Le pendant de SQL pour XML se nomme XPath.
 Sommaire


 Introduction

Tout document XML peut se voir représenté par un arbre contenant des noeuds. Chacun de ces noeuds correspond à une entité bien précise du document XML représenté.

On dresse ainsi la liste des noeuds possibles :
  • noeud élément
  • noeud texte
  • noeud attribut
  • noeud instruction de traitement
  • noeud commentaire
  • noeud déclaration d'espace de nommage

En réalité, cette liste incarne la liste des noeuds existant dans le langage XPath. La norme XML utilise cinq autres noeuds auxquels XPath n'a pas accès. Quel est donc le lien entre ces fameux noeuds et XPath ?

Pour simplifier la localisation de données spécifiques dans un document XML, le langage XPath a été créé. Ressemblant par certains côtés aux chemins d'accès à des fichiers sur un disque dur, XPath constitue un langage d'adressage.

Afin de connaître l'ensemble des balises <utilisateur> d'un document XML dont l'attribut prénom est "Caroline" on pourra émettre la requête XPath suivante : //utilisateur[@prenom="Caroline"]. Une requête renvoie le ou les noeuds la satisfaisant.


 Les noeuds éléments

Deux sortes d'expressions, ou requêtes XPath, peuvent être distinguées. Nous utiliserons la seconde forme, la forme simplifiée. La première forme, pour découvrir les balises de type <author name="Clark"> au sein de la balise <book>, imposerait cette forme d'écriture : /child::book/child::author[@name="Clark"].

Pour notre part, nous rédigerons l'expression ainsi : /book/author[@name="Clark"].

Le caractère "/" joue le rôle de séparateur entre deux noeuds. Soit le document XML formé de la sorte :

<livre>
  <chapitre>
    <titre>Chapitre 1</titre>
    <texte>Ce chapitre.</texte>
  </chapitre>
  <chapitre>
    <titre>Chapitre 2</titre>
    <texte>Ce chapitre.</texte>
  </chapitre>
</livre>
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Imaginons que nous souhaitions atteindre les balises <chapitre>. Nous voyons que celles-ci se trouvent au sein de la balise <livre>. La requête est donc /livre/chapitre. Un "/" en première position désigne le document. Il s'avère possible de généraliser les recherches. La séquence "//" indique au processeur XPath de parcourir récursivement tous les noeuds descendants à partir du noeud courant.

En XHTML nous pourrions trouver tous les liens d'un document par le biais de cette expression : /html/body//a. Cela signifie que l'on doit chercher, dans la balise <body> de la balise <html>, tous les noeuds éléments <a> possibles. Le caractère générique "*" désigne tout noeud élément. Il trouve son utilité employé avec les attributs ou les positions. La requête //* renverra la liste de tous les éléments du document.


 Les noeuds attributs

Un document XML contient souvent des balises de même nature que seuls les attributs distinguent. Nous pouvons avoir une liste de noms :

<liste>
  <nom prenom="Claire" famille="Mivielle" />
  <nom prenom="Damien" famille="Palvadeau" />
  <nom prenom="Caroline" famille="Baugey" />
  <nom prenom="Fabrice" famille="Veniard" />
</liste>
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Une requête portant uniquement sur les noeuds éléments nous renverrait l'intégralité des noms. Si nous souhaitons par contre obtenir tous les éléments dont l'attribut prenom vaut "Claire" nous devons introduire une nouvelle notation. Entre crochets se placent des caractéristiques des noeuds. Ainsi, //nom[@prenom="Claire"] recherchera tous les éléments dont l'attribut prenom vaut "Claire". Un attribut est désigné par l'arobase. Ceci est important car il s'avère possible d'utiliser des fonctions XPath, telles que la position du noeud.

Par le biais des opérateurs booléens and et or, le programmeur peut affiner ses recherches :

/liste/nom[@prenom="Claire" or @prenom="Caroline"]
/liste/nom[@famille="Veniard" and @prenom="Fabrice"]
       
      
JextCopier dans Jext
Bien entendu, les specifications des attributes peuvent se voir employees en tout point de la requête. On peut dès lors aboutir à des expressions complexes : /document/section[@name="introduction"]/paragraph[@title="DOM"]. On recherche ici les paragraphes portant le titre "DOM" au sein des sections nommées "introduction".


 Les positions

Outre les attributs, les crochets servent à orienter la recherche sur les positions des noeuds. Deux manières existent de traiter un tel problème. Pour chercher le troisième noeud élément b d'un document nous pouvons écrire: //b[position()=3]. Lorsque seule la position se voit employée, l'expression se simplifie en //b[3]. La fonction position() permet d'utiliser les opérateurs and et or afin de rendre les recherches plus fines. Ainsi, la troisième balise b ou celle portant l'attribut id de valeur "id1" sera trouvée par l'expression //b[position()=3 or @id="id1"]. Nous pourrions enfin consulter la liste de tous les éléments situés en troisième position au sein de leur parent : //*[3].

Deux autres fonctions trouvent leur utilité dans le cadre des positions des noeuds. Il s'agit de last() qui renvoie la position du dernier élément au sein du noeud courant, et count(liste) qui renvoie le nombre d'élément de la liste. Aussi, //name[last()] se veut équivalent à //name[count(//name)].


 Elément sélectionné

Si l'on ne désire pas connaître l'intégralité d'un élément mais seulement l'une de ses caractéristiques, la requête doit être complétée. Dans l'exemple des noms et prénoms, on pourrait demander d'afficher les seuls noms de famille des Damien : //nom[@prenom="Damien"]/@famille. Le dernier "/" peut servir pour appeler des informations du noeud précédemment sélectionné. Outre les attributs, nous pouvons consulter le contenu même de la balise. L'affichage de la liste des mots utilisés comme liens dans un document XHTML est simple : /html/body//a/text(). Nous employons la fonction text(). Cette fonction peut se voir appelée entre les crochets pour sélectionner un attribut. Auquel cas nous devons la coupler avec d'autres fonctions de test.


 Les fonctions

XPath offre de nombreuses fonctions. En voici quelques-unes : starts-with(ch1, ch2), susbtring(ch, nb1, nb2), contains(ch1, ch2), string-length(ch), number(ch), floor(n), ceiling(n), sum(liste-de-noeud), round(n), not(expr). Pour les tests "mathématiques", les opérateurs de comparaison !=, <, >, <=, >= et = sont accessibles. En pratique nous pouvons récupérer la liste des noms de familles de personnes dont le prénom commence par "D" : //name[starts-with(@prenom, "D")]/@last. Nous pourrions aussi afficher les liens d'une page contenant le terme xml.org : /html/body//a[contains(text(), "xml.org")]/text(). En combinant astucieusement ces quelques principes, les programmeurs se voient en mesure d'opérer des recherches très poussées sur des documents XML.

Les requêtes XPath ont une importance considérable dans le langage de transformation XSL. Grâce à ces requêtes beaucoup de choses deviennent possibles lors de la génération d'une page.



par Romain Guy
romain.guy@jext.org
http://www.jext.org
Dernière mise à jour : 14/10/2006



 
#ProgX©2005 Mathieu GINOD - Romain GUY - Erik LOUISE