Skip to content

Les noeuds XML : d'où je veux, quand je veux (XPath) — N°5a/XXX

25/01/2010

Avec les balises <xsl:template match="qqchose"> et <xsl:for-each select="qqchose">, vous placez le processeur XSLT dans un noeud précis d’un document XML connu.

(voir les billets précédents sur les nœuds XML).

La première chose à faire (ou presque) quand on commence une feuille XSL devant être appliquée à un fichier XML, c’est écrire <xsl:template match="/">  </xsl:template> pour se placer à la racine du document. Ensuite seulement on peut se demander ce qu’on veut faire de l’intérieur du fichier XML : quelles informations récupérer, selon quels critères, etc.

Dans les exemples précédents, je me suis toujours placé au niveau de la balise <ville> (en écrivant : <xsl:for-each select="//ville"> du fichier XML, pour traiter les données à partir de cette balise. J’ai traité des éléments enfants ou descendants de <ville> uniquement.

Mais XSL permet aussi de se placer au niveau d’une balise puis de remonter dans l’arborescence, pour récupérer des informations sur l’élément parent, ou un élément ancêtre, ou encore un élément frère.

Rappelons encore une fois la structure du fichier XML servant d’exemple.

Exemple 1 : remonter dans l’arborescence

Je veux avoir la liste des communes pour lesquelles le nombre d’inscrits en 2005 est égal à 0.

Concrètement, ma feuille XSL devra donc :

  1. pour chaque noeud <inscrits> dépendant de <an2005>
  2. voir si la valeur est égale à 0
  3. remonter au niveau de l’ancêtre <ville> (on a la scructure : ville/an2005/inscrits, donc <ville> est ancêtre de <inscrits>)
  4. dans l’élément <ville>, récupérer la valeur du noeud enfant <nom>, de type attribut.

Voilà ce que ça donne

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform&quot; version="1.0">
<xsl:template
match="/">
Je me place au niveau de la racine du document
<xsl:for-each
select="//an2005/inscrits[.=’0′]">
Depuis la racine, je cherche toutes les balises
<inscrits> dépendant de <an2005> (ou que
soit cette balise <an2005>)Attention ! Si j’avais écrit : <xsl:for-each select="//inscrits">,  j’aurais sélectionné aussi les balises <inscrits> dépendant de <an2008>

Mais je ne prends pas tous les <inscrits> : les crochets [.=’0′] me permettent d’indiquer une condition.

Le . définit le noeud en cours (donc <inscrits>)

Je ne sélectionne donc que les balises <inscrits> dont la valeur est égale à 0 (notez l’emploi de guillemets simples)

<xsl:value-of
select=""ancestor::ville/@nom">
Pour chacune de ces balises <inscrits> répondant aux conditions énoncées ci-dessus, je vais chercher une balise ancêtre du nom de ville.Et pour cette balise, je récupère la valeur de son attribut @nom
<xsl:text> </xsl:text> J’ajoute un saut de ligne entre chaque nom de commune
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Et j’obtiens ceci :
Marboz
Saint-Georges-de-Didonne
La Roche-Chalais
Novéant-sur-Moselle
Chevrières
Rhinau
Blacé
Provins
Roissy-en-Brie
Beauvoir-sur-Niort
Bonifacio

Exemple 2 : les noeuds frères

Il peut être aussi intéressant, pour les villes ci-dessus, de récupérer le nombre d’habitants total pour 2005.

Il me faut donc enrichir ma feuille XSL d’une ligne supplémentaire permettant, depuis le nœud an2005/inscrits, de récupérer le nœud an2005/population.

Voici le fichier XSL ci-dessus modifié en conséquence :
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform&quot; version="1.0">
<xsl:template match="/">
<xsl:for-each select="//an2005/inscrits[.=’0′]">
<xsl:value-of select="ancestor::ville/@nom"/>
<xsl:text> : </xsl:text>
<xsl:value-of select="preceding-sibling::population"/>

<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Explications

  • La première ligne en gras permettra de séparer le nom de la ville et sa population par deux points ":"
  • La seconde ligne sélectionne un noeud frère du noeud <inscrits>, ayant le même parent (donc <an2005>) mais situé avant lui (preceding), et de nom "population". En anglais, le terme "Sibling" permet de désigner indifféremment un frère ou une soeur, càd l’enfant d’un même parent.
    Remarque importante : lorsque nous voulons "attraper" la valeur de la balise <population>, je pars toujours du noeud an2005/inscrits. Je viens juste de récupérer le nom de la ville, mais le nœud contexte reste celui défini par la balise <xsl:for-each>. La balise <xsl:value-of> ne modifie pas le nœud contexte à partir duquel je vais sélectionner mes valeurs.

Et j’obtiendrai cette liste :
Marboz : 2207
Saint-Georges-de-Didonne : 5133
La Roche-Chalais : 2913
Novéant-sur-Moselle : 1835
Chevrières : 1710
Rhinau : 2371
Blacé : 1231
Provins : 12091
Roissy-en-Brie : 19762
Beauvoir-sur-Niort : 1358
Bonifacio : 2705

Publicités
%d blogueurs aiment cette page :