IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XSL/XSLT/XPATH XML Discussion :

[XML/DTD/XSL/CSS/HTM] Affichage d'images (tutorial)


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 3
    Points : 3
    Points
    3
    Par défaut [RESOLU] [XML/DTD/XSL/CSS/HTM] Affichage d'images (tutorial)
    [XML/DTD/XSL/CSS/HTM] Exemple affichage d'images (tutorial)


    Bonjour !

    j'avance pas à pas en xml/xsl -> html, dans le but de créer des galeries de photos paramétrées...


    [EDIT : je pense que c'est un bon exemple pour avancer en xsl après vous être ingurgité les tutoriels XML/DTD/XSL disponibles sur le net.
    Voir solution tutorisée (tutorialisée?) dans le message suivant]

    Définition du problème :

    pour chaque paragraphe, j'insère un nombre variable d'images :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    <!ELEMENT paragraphe (posparag,info,image+,commentaire*)>
    <!ATTLIST paragraphe pos_page ID #REQUIRED>
    <!ELEMENT info (#PCDATA)>
    <!ELEMENT image (#PCDATA)>
    <!ATTLIST image l_orig NMTOKEN #REQUIRED h_orig NMTOKEN #REQUIRED>
    <!ELEMENT commentaire (auteur,texte,jour,mois,année)>
    si je veux retailler les images pour qu'elles s'affichent sur une ligne,
    j'ai une solution ($larg_page est la largeur imposée de la page) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    <xsl:variable name="larg_imgs">
      <xsl:value-of select="sum(image/@l_orig)" />
    </xsl:variable>
     
    <xsl:for-each select="image">
     <img alt="marche pas">
       <xsl:attribute name="src"><xsl:value-of select="." /></xsl:attribute>
       <xsl:attribute name="width"><xsl:value-of select="number(@l_orig * $larg_page div $larg_imgs)" /></xsl:attribute>
       <xsl:attribute name="height"><xsl:value-of select="number(@h_orig * $larg_page div $larg_imgs)" /></xsl:attribute>
      </img>
      <xsl:text> </xsl:text>
    </xsl:for-each>
    Maintenant, si je veux améliorer cet affichage, et faire en sorte que les images aient la même hauteur, et soient toujours affichés sur une largeur imposée, ça se complique, j'ai maintenant besoin de la somme des rapports hauteur/largeur des images.
    et bien sûr, le code suivant serait trop simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      <!-- A MARCHE PAS -->
      <xsl:variable name="larg_imgs">
       <xsl:value-of select="sum(image/@l_orig div image/@h_orig)" />
      </xsl:variable>
    j'ai essayé pas mal d'autres formulations, jusqu'à recréer une variable node avec en éléments les rapports l/h, mais je ne crois pas avoir le droit d'en calculer la somme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
      <!-- A MARCHE PAS -->
      <xsl:variable name="test" >
       <racine>
       <xsl:for-each select="image">
        <element>
        <xsl:value-of select="number(@l_orig div @h_orig)" />
        </element>
       </xsl:for-each>
       </racine>
      </xsl:variable>
      <p>
      <xsl:value-of select="sum($test)" />
      </p>
    Voilà !

    PS :
    pour ceux que ça intéresse, à partir de n images, pour les afficher sur sur largeur X, et qu'elles aient la même hauteur sans modifier leur ratio h/l
    x'i = (xi / yi ) * (X / (somme[1..n](xi/yi)))
    y'i = yi * x'i / xi

  2. #2
    Candidat au Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Une bonne galère c'te problème...

    j'ai fini par trouver une solution (unique?) grâce à l'ébauche de la faq
    http://www.developpez.net/forums/viewtopic.php?t=90007
    Donc merci à grégory !

    pour les débutants qui tomberaient ici, je vais essayer d'expliquer la solution en détail,
    pour les pros, vos commentaires, conseils et corrections seront gratifiés et gratifiants.
    (le code n'est pas optimisé, il est le plus clair possible,
    ça fait deux jours que je débute avec ce langage,
    et je suis maçon d'origine ;-)

    J'en ai fait des tartines bien beurrées, c'est peut-être un peu lourd,
    s'il reste des points peu clairs, n'hésitez pas à proposer des corrections.

    On y va ?

    Rappel de la DTD (simplifiée) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <!ELEMENT site (parametres,page+)> 
    <!ELEMENT page (paragraphe+)>
    <!ELEMENT paragraphe (image+)>
    <!ELEMENT image (#PCDATA)>
    <!ATTLIST image l_orig NMTOKEN #REQUIRED h_orig NMTOKEN #REQUIRED>
    Exemple de fichier xml :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    <!DOCTYPE librairie SYSTEM "generique.dtd">
    <site>
       <page>
          <paragraphe pos_page="ab2">
             <image l_orig="600" h_orig="398">exemple3.jpg</image>
             <image l_orig="600" h_orig="511">exemple4.jpg</image>
             <image l_orig="600" h_orig="426">exemple5.jpg</image>
          </paragraphe>
          <paragraphe pos_page="ab1">
             <image l_orig="600" h_orig="404">exemple1.jpg</image>
             <image l_orig="600" h_orig="404">exemple1.jpg</image>
             <image l_orig="600" h_orig="404">exemple1.jpg</image>
          </paragraphe>
          <paragraphe pos_page="ab3">
             <info>Info du paragraphe3</info>
             <image l_orig="600" h_orig="180">exemple2.jpg</image>
             <image l_orig="600" h_orig="180">exemple2.jpg</image>
          </paragraphe>
       </page>
    </site>
    Contraintes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Chaque <p>paragraphe</p> doit contenir toutes les images sur une seule ligne
    en fonction de la largeur du paragraphe qui est imposée ($larg_page)
    La hauteur des images sera identique (pour chaque ligne)
    Le ratio hauteur/largeur des images ne doit pas être modifié
    Après un bon moment passé sur papier, j'abouti au résultat suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    l_new = (l_orig * larg_page) / (h_orig * tot_ratio)
    h_new = (l_new * (h_orig / l_orig)
    avec tot_ratio = somme de tous les rapports largeur / hauteur des images
    La difficulté vient principalement de ce calcul tot_ratio,
    qui ne peut être réalisé simplement avec un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    "sum(@l_orig div @h_orig)"
    D'après grégory, la seule solution est la méthode itérative
    (puisqu'une xls:variable est en fait une constante :-/)

    Plongeons et creusons pas à pas notre trou (ou plutôt résultat) :
    Le principe consiste à calculer le ratio de la première image,
    puis de le "transmettre" à l'image suivante, qui l'additionnera
    à son propre ratio avant de l'envoyer à l'image d'après etc...
    jusqu'à ce qu'il n'y ait plus d'image (dans le paragraphe).

    Lorsqu'il n'y a plus d'image, il n'y a plus de ratio à calculer,
    on affiche alors la valeur qui a été transmise par l'image précédente,
    (qui était logiquement la dernière du paragraphe).

    Techniquement, on utilisera une fonction avec deux paramètres :
    - la somme des ratios envoyée par l'image précédente
    - la "référence" de l'image courante, celle qu'il faut traiter

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    <!-- Définition de la fonction -->
    <xsl:template name="somme_ratios">
       <!-- et ses deux paramètres -->
       <xsl:param name="total"/>
       <xsl:param name="position"/>
     
       <!-- Ici viendra l'implémentation de la fonction -->
     
    </xsl:template>
    La fonction doit être capable de lire la largeur et la hauteur de l'image courante :
    Rq : on prendra soin d'appeler cette fonction à partir d'un noeud parent de image,
    donc à partir de "paragraphe" dans notre cas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <xsl:variable name="largeuri"><xsl:value-of select="image[position()=$position]/@l_orig"/></xsl:variable>
    <xsl:variable name="hauteuri"><xsl:value-of select="image[position()=$position]/@h_orig"/></xsl:variable>
    Mais que se passe-t-il si la position à laquelle nous nous trouvons ne correspond plus à une image ?
    Nous renverrons le résultat !
    Il va falloir tester cette condition :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    <xsl:choose>
     
      <xsl:when test="$position &lt;= count(image)">
    	<!-- en clair : test="$position <= count(image)", ou encore
             notre position actuelle est-elle inférieure ou égale au nombre d'images de ce paragraphe ? -->
    	<!-- C'est le cas général, il y a une image à cette position -->
      </xsl:when>
     
      <xsl:otherwise>
            <!-- Sinon, il n'y a plus d'image, on renvoie le résultat -->
      </xsl:otherwise>
    </xsl:choose>
    Dans le cas général, il faudra calculer le ratio de l'image courante, l'additionner à la somme des ratios des images précédentes, et transmettre le tout à l'image suivante (qu'elle existe ou pas, nous avons vu que si elle n'existe pas, on prend alors la décision de renvoyer le résultat).
    c'est là qu'intervient la récursivité, nous sommes dans une fonction et nous rappelons cette même fonction,
    mais avec des paramètres qui auront évolués (le $total a changé, et la position est incrémentée) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <xsl:call-template name="somme_ratios">
      <xsl:with-param name="total"><xsl:value-of select="$total+$largeuri div $hauteuri"/></xsl:with-param>
      <xsl:with-param name="position"><xsl:value-of select="$position+1"/></xsl:with-param>
    </xsl:call-template>
    Dans le cas final, on se contente d'afficher le total passé en paramètre
    (pour les sceptiques : ça marche !)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    <xsl:value-of select="$total"/>
    exemple de fonctionnement si nous avons 3 images :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    tot_ratio(tot=0,pos=1)
      il y a une image (pos=1<=nb_img=3)
      ->tot_ratio(tot=ratio1,pos=2)
         il y a une image (pos=2<=nb_img=3)
         ->tot_ratio(tot=r1+r2,pos=3)
           il y a une image (pos=3<=nb_img=3)
           ->tot_ratio(tot=r1+r2+r3,pos=4)
             il n'y a plus d'image
             -> AFFICHE tot
           <- tot est affiché
           fin fonction(pos=4)
         <- tot est affiché
         fin fonction(pos=3)
      <- tot est affiché
      fin fonction(pos=2)
    <-tot est toujours affiché
    fin de la fonction initiale,
    Assemblons le tout :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
    <!-- définition de la fonction et de ses deux paramètres -->
    <xsl:template name="somme_ratios">
     <xsl:param name="total"/>
     <xsl:param name="position"/>
     
      <!-- à dé-commenter pour voir le fonctionnement de plus près
          (mais attention, nous modifiez le fonctionnement en ajoutant des affichages
           et ne pourrez plus exploiter le résultat)
        <xsl:text>Appel fonction (total = </xsl:text>
        <xsl:value-of select="$total"/>
        <xsl:text>; position = </xsl:text>
        <xsl:value-of select="$position"/>
        <xsl:text>)</xsl:text><br />
      -->
     
    <!--Dans quel cas somme-nous ? --> 
     <xsl:choose>
     
       <!-- 1: oui, il existe une image -->
       <xsl:when test="$position &lt;= count(image)">
     
          <!-- définition des deux variables largeur et hauteur (lecture d'attributs) -->  	
          <xsl:variable name="largeur_i">
            <xsl:value-of select="image[position()=$position]/@l_orig"/>
          </xsl:variable>
          <xsl:variable name="hauteur_i">
            <xsl:value-of select="image[position()=$position]/@h_orig"/>
          </xsl:variable>
     
          <!-- calcul du ratio l/h de cette image -->	
          <xsl:variable name="ratio_i">
            <xsl:value-of select="number($largeuri div $hauteuri)"/>
          </xsl:variable>
     
          <!-- à dé-commenter pour voir le fonctionnement de plus près
            <xsl:text>Image trouvée, valeurs : larg_i = </xsl:text>
            <xsl:value-of select="$largeur_i"/>
            <xsl:text>; haut_i = </xsl:text>
            <xsl:value-of select="$hauteur_i"/>
            <xsl:text>; ratio_i = </xsl:text>
            <xsl:value-of select="$ratio_i"/>
            <br />
          -->
     
          <!-- puis on passe à l'image suivante, en mettant à jour les paramètres
          <xsl:call-template name="somme_ratios">
            <xsl:with-param name="total">
              <xsl:value-of select="$total+$ratio_i"/>
            </xsl:with-param>
            <xsl:with-param name="position">
              <xsl:value-of select="$position+1"/>
            </xsl:with-param>
          </xsl:call-template>
        </xsl:when>
     
        <!-- 2:Sinon, cas final, plus d'image, on "affiche" le résultat -->
        <xsl:otherwise>
          <!-- à dé-commenter pour voir le fonctionnement de plus près
            <xsl:text>Image non trouvée, fin de la récursivité</xsl:text>
            <xsl:text>Seule la ligne suivante devrait être affichée</xsl:text>
            <br />
          -->
          <xsl:value-of select="$total"/>
        </xsl:otherwise>
     
     </xsl:choose>
     
    </xsl:template>
    La fonction est maintenant écrite, reste à l'initialiser, au bon moment et au bon endroit :

    Dans mon cas, mon fichier xsl commence par définir une "variable" :
    puis traite la racine du xml, et se termine par notre fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    <?xml version="1.0" encoding="iso-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     
     <xsl:variable name="larg_page">900</xsl:variable>
     <xsl:template match="/">
      <html>
       <head>
         <!-- La partie en-tête -->
       </head>
       <body class="defaut">
         <!-- Le corps -->
       </body>
      </html>
     </xsl:template>
     
     <xsl:template name="somme_ratios">
       <!-- La fonction décrite ci-dessus -->
     </xsl:template> 
     
    </xsl:stylesheet>
    C'est bien sûr dans le corps du html que nous ferons notre appel à la fonction.
    Tout d'abord un traitement à réaliser indépendamment, pour chaque paragraphe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <xsl:for-each select="site/page/paragraphe">
      <!-- ... -->
    </xsl:for-each>
    (Rq : vous aurez probablement à traiter chaque page avant
    de traiter chaque paragraphe, hors sujet dans notre cas)

    Dans chaque paragraphe, nous commençons par calculer ce fameux total_ratio,
    on confirme, on vérifie qu'on est bien sur le noeud parent de "image",
    on peut lancer notre calcul itératif :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <xsl:call-template name="somme_ratios">
       <xsl:with-param name="total">0</xsl:with-param>
       <xsl:with-param name="position">1</xsl:with-param>
    </xsl:call-template>
    Le résultat s'affiche à l'écran, et si je veux le stocker ?
    Aussi incroyable que ça puisse paraître, tout simplement
    en encadrant cet appel par une définition de variable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    <xsl:variable name="tot_ratio">
     <xsl:call-template name="somme_ratios">
       <xsl:with-param name="total">0</xsl:with-param>
       <xsl:with-param name="position">1</xsl:with-param>
     </xsl:call-template> 
    </xsl:variable>
    Voilà c'est tout !
    Je ne me défausse pas pour autant, on a bien envie de les voir bien rangées ces images ?
    Nous pouvons les mettre dans un paragraphe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <p class="photo">
      <!-- ... -->
    </p>
    Nous sommes toujours sur le noeud "parapraphe", et nous allons afficher chaque image :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <xsl:for-each select="image">
      <!-- ... -->
    </xsl:for-each>
    Calculons la largeur et la hauteur modifiée de cette image
    (d'après la formule du début et le désormais fameux total_ratio) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    <xsl:variable name="l_new">
      <xsl:value-of select="number(@l_orig * $larg_page div @h_orig div $tot_ratio)" />
    </xsl:variable>    
     
    <xsl:variable name="h_new">
      <xsl:value-of select="number($l_new * @h_orig div @l_orig)" />
    </xsl:variable>
    Et affichons cette image, suivie d'un espace pour les séparer "proprement" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    <img alt="Image introuvable...">
     <xsl:attribute name="src"><xsl:value-of select="." /></xsl:attribute>
     <xsl:attribute name="width">
       <xsl:value-of select="$l_new" />
     </xsl:attribute>
     
     <xsl:attribute name="height">
       <xsl:value-of select="$h_new" />
     </xsl:attribute>
    </img>
    <xsl:text> </xsl:text>
    Bon ben c'est fini ?

    Reste plus qu'à recomposer...
    [mettez tout dans le même répertoire
    exemple.xml (page à appeler dans le navigateur)
    exemple.dtd (appelé par exemple.xml)
    exemple.xsl (appelé par exemple.xml, traité par le navigateur récent)
    exemple.css (appelé par le navigateur via exemple.xsl)
    ]

    exemple.dtd
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    <?xml version="1.0" encoding="iso-8859-1"?>
    <!ELEMENT site (parametres,page+)>
    <!ELEMENT page (paragraphe+)>
    <!ELEMENT paragraphe (image+)>
    <!ELEMENT image (#PCDATA)>
    <!ATTLIST image l_orig NMTOKEN #REQUIRED h_orig NMTOKEN #REQUIRED>
    exemple.xml (pensez à mettre les exemplex.jpg dans le même dossier) :
    l_orig="400" h_orig="398" sont les dimensions originales de l'image
    (un jour je saurais les trouver automatiquement)
    un coup d'explorateur de fichier vous informera facilement...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    <?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
    <!--?xml version="1.0" encoding="iso-8859-1" standalone="no"?-->
    <?xml-stylesheet type="text/xsl" href="exemple.xsl"?>
    <!DOCTYPE librairie SYSTEM "exemple.dtd">
    <site>
       <page>
          <paragraphe>
             <image l_orig="400" h_orig="398">exemple3.jpg</image>
             <image l_orig="700" h_orig="511">exemple4.jpg</image>
             <image l_orig="300" h_orig="426">exemple5.jpg</image>
          </paragraphe>
          <paragraphe>
             <image l_orig="400" h_orig="404">exemple1.jpg</image>
             <image l_orig="200" h_orig="226">exemple1.jpg</image>
             <image l_orig="100" h_orig="324">exemple1.jpg</image>
          </paragraphe>
          <paragraphe>
             <image l_orig="600" h_orig="180">exemple2.jpg</image>
             <image l_orig="600" h_orig="320">exemple2.jpg</image>
          </paragraphe>
       </page>
    </site>
    exemple.css (une feuille de style classique)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    .defaut {
    	color: #CCCCCC;
            font-size: small;
    	text-align: left;
    	background-color: #000000;
    	font-weight: 700;
    }
    .photo {
    	text-align: center;
    }
    exemple.xsl :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
     
    <?xml version="1.0" encoding="iso-8859-1"?>
    <!-- Une feuille de style xsl est un document xml -->
     
    <!-- Début de la feuille de style -->
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     
    <!-- Variables globales, le mieux est de les lire depuis le XML -->
     <xsl:variable name="larg_page">900</xsl:variable>
     
    <!-- Début du traitement, par le noeud racine -->
    <xsl:template match="/">
     <!-- Affichage html -->
     <html>
     
     <!-- La partie en-tête -->
     <head>
      <meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1" /> 
      <meta http-equiv="Content-Language" content="fr" />
      <link href="exemple.css" rel="stylesheet" type="text/css" />
     </head>
     
     <!-- Le corps de la page -->
     <body class="defaut">
      <!-- Pour chaque noeud "paragraphe" -->
      <xsl:for-each select="site/page/paragraphe">
     
       <!-- Calcul de la somme des ratios des images contenues dans chaque paragraphe -->
       <xsl:variable name="tot_ratio">
        <xsl:call-template name="somme_ratios">
         <xsl:with-param name="total">0</xsl:with-param>
         <xsl:with-param name="position">1</xsl:with-param>
        </xsl:call-template>
       </xsl:variable>
     
       <!-- Affichage du paragraphe -->
       <p class="photo">
     
        <!-- Pour chaque image contenue dans le paragraphe -->
        <xsl:for-each select="image">
     
          <!-- Calculs de la largeur et de la hauteur modifiée -->
          <xsl:variable name="l_new">
           <xsl:value-of select="number(@l_orig * $larg_page div @h_orig div $tot_ratio)" />
          </xsl:variable>   
          <xsl:variable name="h_new">
           <xsl:value-of select="number($l_new * @h_orig div @l_orig)" />
          </xsl:variable> 
     
          <!-- La balise image, sur laquelle on ajoute des attributs paramétrables -->
          <img alt="Image introuvable...">
           <xsl:attribute name="src"><xsl:value-of select="." /></xsl:attribute>
           <xsl:attribute name="width"><xsl:value-of select="$l_new" /></xsl:attribute>
           <xsl:attribute name="height"><xsl:value-of select="$h_new" /></xsl:attribute>
          </img>
     
          <!-- Un espace pour décoller les images les unes des autres -->
          <xsl:text> </xsl:text>
     
        </xsl:for-each>
        <!-- Fin du traitement de chaque image -->
     
       </p>
       <!-- Fin du paragraphe -->
     
      </xsl:for-each> 
      <!-- Fin du noeud "paragraphe" -->
     
     </body>
     </html>
     <!-- Fin de la page html -->
     
    </xsl:template>
    <!-- Fin du xml, noeud racine "/" -->
     
     
     
    <!-- Fonction qui calcule la somme des rapports largeur/hauteur, 
         pour tous les noeuds "image" contenu dans le noeud courant  -->
    <xsl:template name="somme_ratios">
     <!-- Paramètres d'entrée, l'appel externe se fait avec total=0 et position = 1 -->
     <xsl:param name="total"/>
     <xsl:param name="position"/>
     
     <!--Dans quel cas somme-nous ? -->
     <xsl:choose>
     
       <!-- 1: oui, il existe une image -->
       <xsl:when test="$position &lt;= count(image)">
     
          <!-- définition des deux variables largeur et hauteur (lecture d'attributs) -->     
          <xsl:variable name="largeur_i">
            <xsl:value-of select="image[position()=$position]/@l_orig"/>
          </xsl:variable>
          <xsl:variable name="hauteur_i">
            <xsl:value-of select="image[position()=$position]/@h_orig"/>
          </xsl:variable>
     
          <!-- calcul du ratio l/h de cette image -->   
          <xsl:variable name="ratio_i">
            <xsl:value-of select="number($largeur_i div $hauteur_i)"/>
          </xsl:variable>
     
          <!-- puis on passe à l'image suivante, en mettant à jour les paramètres -->
          <xsl:call-template name="somme_ratios">
            <xsl:with-param name="total">
              <xsl:value-of select="$total+$ratio_i"/>
            </xsl:with-param>
            <xsl:with-param name="position">
              <xsl:value-of select="$position+1"/>
            </xsl:with-param>
          </xsl:call-template>
        </xsl:when>
     
        <!-- 2 : Sinon, cas final, plus d'image, on "affiche" le résultat -->
        <xsl:otherwise>
          <xsl:value-of select="$total"/>
        </xsl:otherwise>
     
     </xsl:choose>
     <!-- Fin des cas -->
     
    </xsl:template>
    <!-- Fin de la fonction -->
     
    </xsl:stylesheet>
    <!-- Fin de la feuille de style xsl -->

  3. #3
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Bonjour,

    d'abord bravo pour ta solution, et merci d'avoir pris la peine d'exposer en détails ta solution.

    Il y a une alternative à ton utilisation de la variable $position, qui consiste à passer en paramètre non pas l'index de l'image en cours de traitement mais l'élément <image> lui-même. Dans ce cas, l'itération se fait sur chaque élément frère de cet élément, et la condition d'arrêt de la récursivité est un élément vide :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <xsl:call-template name="somme_ratios">
      <xsl:with-param name="elem-image" select="image[1]"/>
    </xsl:call-template>
    ...
     
    <xsl:template name="somme_ratios">
      <xsl:param name="elem-image"/>
      <xsl:param name="total" select="0"/>
      <xsl:choose>
        <xsl:when test="$elem-image/node()">
          <xsl:variable name="largeur_i"> 
            <xsl:value-of select="$elem-image/@l_orig"/> 
          </xsl:variable> 
          <xsl:variable name="hauteur_i"> 
            <xsl:value-of select="$elem-image/@h_orig"/> 
          </xsl:variable> 
          <!-- calcul du ratio l/h de cette image -->    
          <xsl:variable name="ratio_i"> 
            <xsl:value-of select="number($largeuri div $hauteuri)"/> 
          </xsl:variable> 
          <xsl:call-template name="somme_ratios">
             <xsl:with-param name="total" select="$total + $ratio_i"/>
             <xsl:with-param name="elem-image" select="$elem-image/following-sibling::image[1]"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$total"/>
        <xsl:otherwise>
      </xsl:choose>
    <xsl:template>
    A noter également la possibilité de fixer une valeur par défaut pour $total, ce qui dispense de devoir l'initialiser au premier appel de la fonction.
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XML/CSS/XSL] Problème d'affichage des images "dynamiqu
    Par popol55 dans le forum Mise en page CSS
    Réponses: 1
    Dernier message: 06/04/2006, 16h24
  2. affichage plusieurs images collées en CSS
    Par rudwolf dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 23/03/2006, 09h12
  3. [CSS] Affichage d'images sous Firefox & IE
    Par Flushovsky dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 12/06/2005, 12h55
  4. CSS Probléme d'affichage d'images
    Par tebonb dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 01/06/2005, 18h35
  5. XSL: pb d'affichage d'images
    Par enez dans le forum XSL/XSLT/XPATH
    Réponses: 10
    Dernier message: 12/09/2004, 14h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo