Skip to content

Opérations mathématiques simples avec XSL — N°7/XXX

01/03/2010

Désormais, toutes les feuilles XSL montrées génèreront du HTML. Parce que cela permet plus facilement de la mise en forme, des sauts de lignes, des listes, des tableaux, etc.

Donc si la présence de balises HTML au milieu des balises XSL vous perturbe, retournez voir ce billet-là d’abord.

Comme je me suis interrompu un petit mois dans cette série, je rappelle la structure du fichier XML que je continue d’exploiter : à partir des stats de la DLL pour les bibliothèques publiques, j’ai obtenu un fichier qui me donne la liste des villes pour lesquelles nous avons des stats en 2005 et 2008.

Pour chaque ville, ce fichier contient, pour 2005 et 2008, la population globale et le nombre d’inscrits.

Voici le fichier XML contenant ces données

Première opération : calculer le pourcentage d’inscrits ramené à la population totale

Le calcul est simple :

Formule mathématique (Nb d'inscris/population) * 100

Dans une boucle
<xsl:for-each select="//ville">

Je vais donc effecturer d’abord pour <an2005>, puis pour <an2008>, cette opération de division.

Pour diviser le nombre d’inscrits par la population je ne peux pas écrire :
<xsl:value-of select="inscrits/population"/>

Car le processeur chercherait alors un noeud enfant <population> dépendant de <inscrits>. Il me faut donc utiliser une fonction div :

<xsl:value-of select="inscrits div population"/>

Rajoutez à cela toute la mise en forme (balises HTML), avec

  • des métadonnées dans la page HTML (produire une balise <head>) et un titre global
  • un en-tête
  • un affichage en tableau (une ligne par ville)
  • pour chaque ville 3 colonne :
    • le nom de la ville
    • pourcentage en 2005
    • pourcentage en 2008

Voici

Page HTML générée (copie d’écran)

Notez au passage certaines cellules comportant la valeur NaN, signifiant Not a Number. Cela signifie qu’il n’y avait pas de nombre pour le nombre d’inscrits dans le fichier : la population est toujours connue, mais le nombre d’inscrits n’est pas toujours fourni… Donc « rien » divisé par la population, ça ne donne pas 0 : ça ne donne rien.

Décorticage du fichier XSL

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="html"/>
Balise facultative, permettant d’indiquer que le fichier en sortie sera du HTML.

C’est intéressant surtout quand on veut produire du XHTML : alors les balises vides (balises <br>, <img>, etc. seront auto-fermées (<br/>, etc.).

<xsl:template match="/">
On place le processeur à la racine du fichier XML
<html>
On génère en sortie les balises HTML qui vont encadrer les résultats
<head> La balise qui encadre les métadonnées du fichier HTML en sortie
<title>Stats DLL : Pourcentage d'inscrits dans la population</title> Un titre à la page HTML (c’est ce titre qui apparaît dans l’onglet du navigateur)
</head>
<body> Début du corps de la page web (le texte qui va apparaître à l’écran sur le navigateur)
<h3>Pourcentage d'inscrits en bibliothèque publique pour
chaque ville, en 2005 et 2008</h3>
On donne un titre global au tableau
<table border="1"> Création d’un tableau…
<tbody>
<tr>
<th>Ville</th>
<th>%en 2005</th>
<th>% en 2008</th>
</tr>
…avec une ligne d’en-tête

Les 3 colonnes s’intituleront donc :

  • Ville
  • % en 2005
  • % en 2008
<xsl:for-each select="dll/ville"> On crée enfin une boucle

Rappel : le processeur était resté à la racine. Il doit donc chercher une balise racine <dll>, et trouver tous les noeuds enfants <ville> dépendant de <dll>

<tr> Pour chaque ville, on crée une ligne dans le tableau
<td>
<xsl:value-of select="@nom"/>
</td>
Dans chaque ligne, la première cellule est le nom, donc ici : l’attribut @nom de la balise <ville>(le processeur trouvera des informations sous la forme :

<ville nom="Ambronay">

<td>
<xsl:value-of
select="(an2005/inscrits div an2005/population)*100"/>
</td>
Dans la  2e cellule :on cherche, sous la balise <ville>, le noeud an2005/inscrits, qu’on divise par an2005/population et on multiplie le tout par 100

Rq : pour la multiplication, on peut utiliser sans problème l’astérisque *, qui n’a aucune ambiguïté pour le processeur.

Il en est de même des opérateurs + et  -.

<td>
<xsl:value-of select="(an2008/inscrits div
an2008/population)*100"/>
</td>
Dans la 3e cellule : même chose, sauf que <inscrits> et <population> dépendent de <an2008>
</tr> Fin de la ligne de tableau créée pour chaque ville
</xsl:for-each> Fin de la boucle
</tbody>
</table> Fin du tableau
</body> Fin du corps de la page web
</html>
Fin du fichier HTML à
générer
</xsl:template>
Fin de la feuille XSL 🙂
</xsl:stylesheet>

Frustrations (si si !)

On voit assez rapidement plusieurs problèmes (au moins) dans le fichier HTML généré :

  • Aucun tri n’a été fait : les données sont dans l’ordre dans lequel elles ont été trouvées dans le fichier XML. Or on peut vouloir trier :
    • par ordre alphabétique de ville
    • par ordre de taille de ville
    • par pourcentage du nombre d’inscrits
  • Aucun regroupement non plus : il pourrait être intéressant de subdiviser
    • entre villes de petite, moyenne, grande et très grande taille
    • entre villes ayant un faible et fort pourcentage d’inscrits
  • Il faut encore retraiter les données : le pourcentage, c’est bien. Mais savoir s’il augmente ou s’il diminue entre ces deux dates, c’est mieux 🙂
  • Les décimales interminables rendent difficile une lecture rapide. Il faudrait une mise en forme du résultat

Nous traiterons tous ces problèmes les uns après les autres…

Et nous verrons ainsi d’autres opérations

Advertisements
8 commentaires
  1. 04/03/2010 11:19

    À quoi elle sert ta balise ? Je ne l’avais jamais vue, et je n’ai jamais eu de problème avec mes tableaux..
    Et merci pour le que je découvre ! Ça va m’être utile, ça !

    Sinon, toujours aussi clair (pour moi en tout cas), j’attends la suite avec impatience !

  2. 04/03/2010 11:22

    Ok m*** mes balises sont passées en code et ont donc disparus. Malin, moi.
    Je parlais donc en premier lieux de la balise « tbody ».
    Et en second lieu, xsl:output indent= »yes » method= »html ».

    Sorry pour le double post (en espérant que ça fonctionne, maintenant!).

  3. 04/03/2010 11:31

    @SebDeclercq : justement, un prochain billet te permettra de voir comment intégrer des balises avec chevrons dans des commentaires WordPress 😉
    Sinon, la balise <tbody> encadre toujours les balises <tr> qui définissent les lignes.
    Disons que j’ai toujours codé comme ça, parce que je l’ai toujours vu codé ainsi.
    En fait, entre les balises <table> et <tbody> , il peut y avoir des informations donnant un titre au tableau, ou le nombre de colonnes, etc.
    La balise <tbody> est à un tableau ece que la balise <body> est à une page html.

    Pour le <xsl:output indent="yes" method="html"/>
    il définit le format de sortie avec deux intérêts (deux attributs).
    Le premier, indent="yes", indique que les balises en sortie seront indentées : le fichier produit aura un code propre, avec de beaux alignements décalés selon le niveau de profondeur (ils seront <indentés).
    L’autre attribut ne serait pas nécessaire ici car la valeur method="html" n’apporte pas grand chose : il génère du HTML normal.
    Disons que c’est plutôt informatif pour la personne qui relit le code.
    En revanche c’est plus intéressant si je mets method="xhtml" : alors la transformation XSL me produira un fichier XHTML beaucoup plus propre, où j’aurai des balises <br/> au lieu de <br>
    des balises <img src= »image.jpg/>
    au lieu de <img src=image.jpg>.

    Pour le navigateur, le résultat à l’affichage sera identique.
    En revanche pour le programmeur c’est très différent : car les fichiers XHTML seront à leur tour exploitables pour des traitements XSL ultérieurs.
    Exemple : si tu as un site web de 3000 pages, tu pourras extraire avec XSL la liste des liens hypertextes présents dans les pages pour faire des vérifications de validité.

Trackbacks

  1. Trier une liste en XSL – N°8/XXX « Bibliothèques [reloaded]
  2. Techno-fil (07/03/10) « pintiniblog
  3. Filtrer sur un critère – N°9/XXX « Bibliothèques [reloaded]
  4. Définir un format pour les nombres — N°11/XXX « Bibliothèques [reloaded]
  5. Série XSL : Petite synthèse des billets passés (2) « Bibliothèques [reloaded]

Les commentaires sont fermés.

%d blogueurs aiment cette page :