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 :

[XSLT] Grouper les elements identique


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 254
    Points
    28 254
    Par défaut [XSLT] Grouper les elements identique
    la première de mes etapes étant le nettoyage du fichier xml, la second sera le tri par categories. \o/ ca à l'air super marrant à faire en xslt. j'ai tout fait en dotnet en une heure pour vérifier que c'etait faisable mais il me faut maintenant le reussir en xslt.
    J'ai donc des produits comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    <products>
    <product><name>balai</name><class>menager</class></product>
    <product><name>aspi</name><class>menager</class></product>
    <product><name>balayette</name><class>menager petit</class></product>
    </products>
    et j'aimerais créer des classes en rangeant les produits dedans pour obtenir ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    <products>
    <class cls="menager">
    	<product><name>balai</name><product>
    	<product><name>aspi</name><product>
    </class>
    <class cls="menager petit">
    	<product><name>balayette</name><product>
     
    </class>
    </products>

    j'ai donc pensé à ceci.
    -1- je tri les produits par class par ordre alphabétique.
    -2- je boucle sur les produits en faisant ceci
    soit $tmp une variable qui stocke la classe courante et que j'initialise à '' au debut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      for each product  
       if( $tmp=class)
            jajoute le produit
       else
         je met la valeur de la nouvelle class dans $tmp
         je cree la balise class
         j'ajoute le produit
      fin du foreach
    ce qui avec mon niveau (on rigole pas) donne ceci
    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:template match="products" >
        <xsl:copy>
             <xsl:call-template name="tprod" >
               <xsl:with-param name="tmp" select="''" /> 
             </xsl:call-template>
        </xsl:copy>
    </xsl:template>
     
    <xsl:template name="tprod">
    <xsl:param name="tmp" />
      <xsl:for-each select="product">
            <xsl:choose>
                <xsl:when test="$tmp=class"><!-- ce test est-il bon?class est un noeud enfant de product -->
                    <!-- add the product -->
                </xsl:when>
                <xsl:otherwise>
                   <!-- set $tmp with the new class -->
                   <xsl:variable name="tmp">
                        <xsl:value-of select="class" />
                   </xsl:variable>
                   <!-- create prod node -->
                    <prod>
                    <xsl:value-of select="$tmp" />
                    <!-- add the product -->
     
                </xsl:otherwise>
            </xsl:choose>
       </xsl:for-each>
    </xsl:template>

    bien entendu, ca ne marche pas
    1- je ne sais pas comment attribuer une variable globale puis changer sa valeur en cours. p-e que je m'y prend mal et que je devrais appeler un template avec un param mais meme avec ca, j'ai des problemes
    2- combien meme ca marcherait l'attribution de la variable, je ne sais pas quand fermer la balise class. je peux bidouiller, en mettant un </class> apres le foreach, et avec un if($tmp!='') <class> dans le else (otherwise) mais est-ce propre?


    edit apres recherche
    parce qu'on ne peut pas redefinir une variable, je crois que mon salut est dans l'appel de template recursif et pourtant mes essais son infructueux. soit ca me dis des erreurs comme quoi je fais nimporte quoi, soit ca me sort rien.

    j'ai peur de partir dans n'importe quoi. je suis trop habitué à coder objet et j'ai l'impression de n'avoir pas l'abstraction necessaire pour utiliser proprement xslt. P-e pourriez-vous au moins me donner l'algo general de la chose

    indice:
    quand j'arriverai a obtenir les produits dans chaque class, j'aurais une derniere etape: ajouter a chaque class deux attributs:
    taillemax: qui represente la taille des produits: (petit, moyen,grand) si ca possede pleins de petits colis et un grand, alors taillemax = grand

    poids: qui represente le poids total des colis, on va dire que quand c'est un produit petit, j'ajoute 1kg au total, 2kg pour le moyen 3kg pour le grand

    pour jespere que c'est possible, obtenir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    <products>
    <class cls="menager" taillemax="grand" poids="6">
    	<product><name>balai</name><size>petit</size><product>
    	<product><name>aspi</name><size>grand</size><product>
            <product><name>aspi2</name><size>petit</size><product>
            <product><name>marteau</name><size>petit</size><product>
    </class>
    <class cls="menager petit" taillemax="moyen" poids="6">
    	<product><name>balayette</name><size>moyen</size><product>
     
    </class>
    </products>
    je peux p-e faire les deux avec un seul xslt mais à vrai dire, ca m'importe peu d'en utiliser un ou 50 du moment que le resultat final est là

    je ne suis pas un adepte du faites moi mon truc donc un algo qui me guiderait suffisemment me plairait amplement. merci d'avance

  2. #2
    Membre éprouvé
    Profil pro
    Responsable Dev
    Inscrit en
    Décembre 2003
    Messages
    788
    Détails du profil
    Informations personnelles :
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Responsable Dev

    Informations forums :
    Inscription : Décembre 2003
    Messages : 788
    Points : 1 063
    Points
    1 063
    Par défaut
    un petit cour sur les variable ici

  3. #3
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 254
    Points
    28 254
    Par défaut
    Citation Envoyé par fraoustin
    un petit cour sur les variable ici
    c'est gentil mais j'ai bien entendu commencé par là

  4. #4
    Futur Membre du Club
    Inscrit en
    Mars 2006
    Messages
    10
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 10
    Points : 6
    Points
    6
    Par défaut
    Si j'ai bien compris, c'est impossible de créer un compteur en XSL, en tout cas, pas avec une variable puisqu'il est impossible de modifier une variable en XSL

    Faut faire autrement...

  5. #5
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 254
    Points
    28 254
    Par défaut
    Citation Envoyé par lautux
    Si j'ai bien compris, c'est impossible de créer un compteur en XSL, en tout cas, pas avec une variable puisqu'il est impossible de modifier une variable en XSL

    Faut faire autrement...
    oui c'est aussi ce que j'en ai conclu tard dans la nuit et il me reste donc les templates parametrés mais je ne sais pas comment detecter que le produit n'appartient pas à la classe courrante et qu'il me faut créer un nouveau noeud <class> pour y ranger les produits.


    p-e devrais-je penser à une autre structure comme ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <classes>
    <class>chaque classe ici</class>
    </classes>
    <products>
    products
    </products>

  6. #6
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 254
    Points
    28 254
    Par défaut
    bon j'ai trouvé une solution. passer par xslt 2.0 et utiliser
    <xsl:for-each-group

    j'ai pas encore tout ce que je voulais mais ca avance

  7. #7
    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
    Si tu comptes utiliser XSLT 2.0, sache que MSXML et la librairie XML de DotNet n'implémentent pas cette version de XSLT.

    Ca reste tout à fait faisable avec XSLT 1.0, en utilisant la méthode Muench : http://xml.developpez.com/faq/?page=3#xslt_regroup

    Tu trouveras aussi de nombreux posts sur cette méthode de regroupement dans le forum.

  8. #8
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 254
    Points
    28 254
    Par défaut
    oui mais j'utilise saxon pour permettre la portabilité du truc et surtout parce qu'on m'a dit que si je voulais faire tout ce que je souhaite avec un seul xslt, je devrai utiliser saxon. la personne n'a pas su m'expliquer pourquoi

    maintenant je galere pour trouver la valeur maximum d'un attribut dont les valeur sont petit, moyen, grand. je pense que je vais ajouter un attribut temporaire qui vaudra 1,2, ou 3
    bref, on verra

  9. #9
    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
    Citation Envoyé par Louis-Guillaume Morand
    oui mais j'utilise saxon pour permettre la portabilité du truc et surtout parce qu'on m'a dit que si je voulais faire tout ce que je souhaite avec un seul xslt, je devrai utiliser saxon. la personne n'a pas su m'expliquer pourquoi
    Sans doute parce que Saxon est un des rares processeurs XSLT à implémenter XSLT 2.0. Maintenant, les problèmes qui nécessitent absolument XSLT 2.0 parce qu'impossibles à traiter avec la 1.0 sont quand même très rares. Ce sera plus ou moins complexe à coder avec la 1.0, mais on s'en sort pratiquement toujours.
    Citation Envoyé par Louis-Guillaume Morand
    maintenant je galere pour trouver la valeur maximum d'un attribut dont les valeur sont petit, moyen, grand. je pense que je vais ajouter un attribut temporaire qui vaudra 1,2, ou 3
    bref, on verra
    Pas besoin d'attribut temporaire : tes valeurs "petit", "moyen" et "grand" sont dans un ordre alphabétique inverse à celui de l'ordre de grandeur qu'elles représentent ; il suffit de tirer parti de cette caractéristique.

  10. #10
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 254
    Points
    28 254
    Par défaut
    Citation Envoyé par GrandFather
    Pas besoin d'attribut temporaire : tes valeurs "petit", "moyen" et "grand" sont dans un ordre alphabétique inverse à celui de l'ordre de grandeur qu'elles représentent ; il suffit de tirer parti de cette caractéristique.
    t'sais que c'est pas bête ça
    sauf que j'aimerai récupérer la valeur max (donc en triant et en prenant la position 1) sauf que ca marche pas. en regardant sur le forum, j'ai compris que lorsqu'on "sort" c'est en live et donc position()=1 se base sur la position avant le tri donc le code suivant ne marche pas.

    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
    <xsl:template match="products" >
        <xsl:copy>
                <xsl:for-each-group select="product" group-by="@class">
                 <class>
                 <xsl:attribute name="class" select="current-grouping-key()"/>
                 <xsl:attribute name="maxsize" select="type[position()=1]"/>
                 <xsl:for-each select="current-group()">
                 <xsl:sort order="ascending" data-type="text" select="type" />
                      <product>
                          <title><xsl:value-of select="name"/></title>
                          <manufacturer><xsl:value-of select="manufacturer"/></manufacturer>
                          <type>
                          <xsl:attribute name="productsize" select="type/@productsize" />
                          <xsl:value-of select="type" /></type>
                      </product>
                 </xsl:for-each>
                 </class>
                </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>
    et c'est donc
    <xsl:attribute name="maxsize" select="type[position()=1]"/>
    qui ne marche pas. cela vous parait p-e simple la solution mais pour moi, c'est une façon de coder qui n'est pas mienne.

    est-ce que je dois faire le premier groupement, le mettre dans une variable, et ressortir le contenu de la variable en triant? le probleme c'est que je suis habitué en codant à debugger et donc pouvoir voir le contenu d'une variable au cours de l'execution de mes programmes.
    j'ai donc essayé quelque chose qui ressemble à ceci:

    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
    <xsl:template match="products" >
        <xsl:copy>
       <xsl:variable name="toto">
                <xsl:for-each-group select="product" group-by="@class">
                 <class>
                 <xsl:attribute name="class" select="current-grouping-key()"/>
                 <xsl:for-each select="current-group()">
                 <xsl:sort order="ascending" data-type="text" select="type" />
                      <product>
                          <title><xsl:value-of select="name"/></title>
                          <manufacturer><xsl:value-of select="manufacturer"/></manufacturer>
                          <type>
                          <xsl:attribute name="productsize" select="type/@productsize" />
                          <xsl:value-of select="type" /></type>
                      </product>
                 </xsl:for-each>
                 </class>
                </xsl:for-each-group>
       </xsl:variable>
        </xsl:copy>
     
       <!-- travailler sur $toto -->
      <xsl:for-each select="$toto">
                 <xsl:attribute name="maxsize" select="type[position()=1]"/>
     
         <!-- plein de trucs super marrants mais dont aucun marche -->
    </xsl-for-each>
     
    </xsl:template>
    suis-je dans la bonne direction? ou fais-je n'importe quoi de tellement mal codé que l'inventeur du xslt en viendrait à me maudire ?

  11. #11
    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
    Quelque chose qui fonctionne avec XSLT 1.0 & 2.0 :
    Code xml : 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
     
    <xsl:key name="produits" match="class" use="."/>
     
    <xsl:template match="products">
      <xsl:copy>
        <xsl:for-each select="product/class[generate-id(.)=generate-id(key('produits', .)[1])]">
          <xsl:sort select="." order="descending"/>
          <xsl:if test="position() = 1">
            <class cls="{.}">
              <xsl:for-each select="/products/product[class = current()]/name">
                <product>
                  <name><xsl:value-of select="."/></name>
                </product>
              </xsl:for-each>
            </class>
          </xsl:if>
        </xsl:for-each>
      </xsl:copy>
    </xsl:template>

    Par contre, il faut peut-être que tu adaptes à ton schéma XML réel ; parce que dans tes exemples un coup class est un attribut, un autre coup c'est un élément...

  12. #12
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 254
    Points
    28 254
    Par défaut
    Citation Envoyé par GrandFather
    Par contre, il faut peut-être que tu adaptes à ton schéma XML réel ; parce que dans tes exemples un coup class est un attribut, un autre coup c'est un élément...
    quel oeil de lynx
    oui mais c'est le but
    enfin disons qu'a l'origine, la class ou le type ou autre sont des noeuds de chaque produit mais quand je les regroupe sous un noeud class, je prefere a ce moment le mettre en attribut puisque il est unique et je trouve ca plus lisible. je teste ton code de suite. merci

  13. #13
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 254
    Points
    28 254
    Par défaut
    je viens (enfin) de réussir à faire marcher ton bout d'xslt. c'est bien le trucmuche de Munchen c'est ca?
    j'obtiens exactement le meme résultat qu'avec l'instruction <xsl:for-each-group> mais il me semble avoir lu (je retrouve plus où) que la solution 2.0 etait plus efficace que le tri de münchen et que si on pouvait utiliser la seconde, autant le faire.

    donc là j'ai deux choses qui à partir de ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <products>
       <product class="jardin">
          <name>tractopelle</name>
          <type productsize="15">small normal</type>
       </product >
       <product class="jardin">
          <name>rateau</name>
          <type productsize="40">large normal</type>
       </product >

    me produisent ceci (juste un regroupement par classe)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <products>
       <class cls="jardin" >
          <product>
             <name>rateau</name>
             <type productsize="40">large normal</type>
          </product>
          <product>
             <name>tractopelle</name>
             <type productsize="15">small normal</type>
          </product>
       </class>
    maintenant, il me faudrait obtenir ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <products>
       <class cls="jardin" maxsize="large normal" size="70">
          <product>
             <name>rateau</name>
             <type productsize="40">large normal</type>
          </product>
          <product>
             <name>tractopelle</name>
             <type productsize="15">small normal</type>
          </product>
       </class>
    en gros:
    size = sum(product/type/@productsize)
    et maxsize = /type[position()=1] apres avoir classé par ordre croissant du type


    le (l'un des ) probleme que je rencontre avec ta solution c'est que le foreach se fait sur l'attribut @class mais avec ta méthode ca me dit
    "The child axis starting at an attribute() node will never select anything"
    et donc si j'essaie de placer un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:sort select="../type" order="ascending" data-type="text"  />
    j'ai plus le warning mais ca ne marche pas pour autant
    donc actuellement, j'arrive à trier par type uniquement avec 2.0 malheureusement, il me faut deux etapes pour recuperer la position 1 (et encore j'arrive pas la seconde etape)
    et pour la somme de chaque classe, je pensais qu'un sum(type/@productsize) marcherait (ou au pire ne marcherait pas) mais ca me sort la valeur du premier element productsize
    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
    <xsl:template match="products" >
        <xsl:copy>
                <xsl:for-each-group select="product" group-by="@class">
                 <class>
                 <xsl:attribute name="class" select="current-grouping-key()"/>
                 <!-- sum qui marche bizarrement -->
                 <xsl:attribute name="size" select="sum(type/@productsize)"/>
                 <xsl:for-each select="current-group()">
                 <!-- sera utilisé pour recuperer la plus grande taille -->
                 <xsl:sort order="ascending" data-type="text" select="type" />
                      <product>
                          <name><xsl:value-of select="title"/></name>
                          <type>
                          <xsl:attribute name="productsize" select="type/@productsize" />
                          <xsl:value-of select="type" /></type>
                      </product>
                 </xsl:for-each>
                 </class>
                </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

  14. #14
    Rédacteur
    Avatar de Louis-Guillaume Morand
    Homme Profil pro
    Cloud Architect
    Inscrit en
    Mars 2003
    Messages
    10 839
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Cloud Architect
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 10 839
    Points : 28 254
    Points
    28 254
    Par défaut
    je continue mon petit bonhomme de chemin
    en remplaçant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:attribute name="size" select="sum(type/@productsize)"/>
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:attribute name="size" select="sum(current-group()/type/@productsize)"/>
    la somme semble marcher correctement.
    en y réfléchissant le for-each-group se base sur des nodes uniques avant de les rassembler par groupe. c'est donc logique


    edit: pour le max comme ca ne marche pas sur des chaines de caracteres et que le position()=1 n'est utilisable que lors d'un second appel, j'ai utilisé la méthode en donnant une valeur numérique à chaque taille puis je retransforme. c'est porcos mais bon...

  15. #15
    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
    C'est tout à fait faisable en une seule passe, et avec XSLT 1.0. La preuve :
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    	<xsl:key name="classes" match="@class" use="."/>
    	<xsl:template match="products">
    		<xsl:copy>
    			<xsl:apply-templates select="product/@class[generate-id(.) = generate-id(key('classes', .)[1])]"/>
    		</xsl:copy>
    	</xsl:template>
    	<xsl:template match="@class">
    		<class cls="{.}" size="{sum(key('classes', .)/../type/@productsize)}">
    			<xsl:attribute name="maxsize">
    				<xsl:call-template name="taille-max">
    					<xsl:with-param name="classe" select="."/>
    				</xsl:call-template>
    			</xsl:attribute>
    			<xsl:for-each select="key('classes', .)/..">
    				<xsl:sort select="type"/>
    				<product>
    					<xsl:copy-of select="*"/>
    				</product>
    			</xsl:for-each>
    		</class>
    	</xsl:template>
    	<xsl:template name="taille-max">
    		<xsl:param name="classe"/>
    		<xsl:for-each select="key('classes', $classe)/../type">
    			<xsl:sort select="."/>
    			<xsl:if test="position() = 1">
    				<xsl:value-of select="."/>
    			</xsl:if>
    		</xsl:for-each>
    	</xsl:template>
    </xsl:stylesheet>
    Une solution XSLT 2.0 serait sans doute plus performante, mais celle-ci a l'avantage d'être portable et de fonctionner sur tous les processeurs du marché (il y a très peu de processeurs 2.0).

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

Discussions similaires

  1. Compter les elements identiques
    Par EIN-LESER dans le forum Requêtes
    Réponses: 2
    Dernier message: 11/02/2013, 09h00
  2. Grouper les entrées identiques
    Par mynameis dans le forum Requêtes
    Réponses: 4
    Dernier message: 12/11/2008, 17h10
  3. [XSLT]xsl:sort qui classe mal les éléments (apostrophe)
    Par strat0 dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 31/07/2007, 14h14
  4. [VB6] [FileListBox] Récupérer les éléments sélectionnés
    Par tomnie dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 22/10/2002, 09h11
  5. [Documentation][XSLT][XSLFO]Les balises xslfo
    Par Lydiane dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 14/08/2002, 11h31

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