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] Regroupement et méthode Muench


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 71
    Points : 77
    Points
    77
    Par défaut [XSLT] Regroupement et méthode Muench
    Bonjour,

    Après avoir lu la FAQ, exploré via Google les sites qui donnent des exemples, je ne parviens à obtenir ce que je souhaite de mon fichier XSL.

    Voici un exemple de fichier XML que j'ai en entrée :

    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="UTF-8"?>
    <FICHIER>
      <STM>
      <ENS REFCONTRAT="X">
        <EXE ANNEE="2005">
          <CRE MNDETCRE="15EUR" />
        </EXE>
      </ENS>
      <ENS REFCONTRAT="X">
        <EXE ANNEE="2006">
          <CRE MNDETCRE="15EUR" />
        </EXE>
      </ENS>
      <ENS REFCONTRAT="Y">
        <EXE ANNEE="2006">
          <CRE MNDETCRE="30EUR" />
        </EXE>
      </ENS>
      <STM>
    <FICHIER>
    Ce que je souhaiterais en sortie :

    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
     
    <FICHIER>
      <STM>
      <ENS REFCONTRAT="X">
        <EXE ANNEE="2005">
          <CRE MNDETCRE="15EUR" />
        </EXE>
     
        <!-- Je regroupe les balises EXE appartenant au même contrat (ici le contrat X) -->
        <EXE ANNEE="2006">
          <CRE MNDETCRE="15EUR" />
        </EXE>
     
      </ENS>
      <ENS REFCONTRAT="Y">
        <EXE ANNEE="2006">
          <CRE MNDETCRE="30EUR" />
        </EXE>
      </ENS>
      <STM>
    <FICHIER>
    J'ai essayé avec la feuille de style suivante :

    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
     
    <?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="group-by-ENS" match="ENS" use="@REFCONTRAT"/>  
     
      <xsl:template match="/FICHIER/STM"> 
     
          <xsl:apply-templates select="ENS[generate-id(.)=generate-id(key('group-by-ENS',@REFCONTRAT)[1])]"/>
     
      </xsl:template> 
     
      <xsl:template match="ENS">
    		<t>
    			<xsl:copy-of select="."/>
    			<xsl:apply-templates select="//EXE[parent::ENS/@REFCONTRAT=current()/@REFCONTRAT]"/>
    		</t>
    	</xsl:template>
     
    	<xsl:template match="EXE">
    		<xsl:copy-of select="."/>
    	</xsl:template>
     
    </xsl:stylesheet>
    mais j'obtiens 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
     
    <?xml version="1.0" encoding="UTF-8"?>
     
      <t>
      <ENS REFCONTRAT="X">
        <EXE ANNEE="2005">
          <CRE MNDETCRE="15EUR"/>
        </EXE>
      </ENS>
      <EXE ANNEE="2005">
          <CRE MNDETCRE="15EUR"/>
        </EXE>
      <EXE ANNEE="2006">
          <CRE MNDETCRE="15EUR"/>
        </EXE>
    </t><t>
      <ENS REFCONTRAT="Y">
        <EXE ANNEE="2006">
          <CRE MNDETCRE="30EUR"/>
        </EXE>
      </ENS>
      <EXE ANNEE="2006">
          <CRE MNDETCRE="30EUR"/>
        </EXE>
    </t>
    ce qui est presque correct : le seul problème vient de la mauvaise imbrication des balises.

    J'ai essayé d'autres méthodes (avec des for-each et autres) mais c'est ce dernier fichier XSL qui se rapproche le plus de ce que je souhaite obtenir.

    Quelqu'un aurait-il une idée ? Suis-je sur la bonne voie ?

    D'avance, merci.

    derek.mf

  2. #2
    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,

    c'est à cause du copy-of : il te recopie la balise ENS et tout son contenu, sans que tu puisses insérer quoi que ce soit d'autre. Il vaut mieux passer par cette construction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <xsl:copy>
      <xsl:copy-of select="@REFCONTRAT"/>
      <xsl:apply-templates select="//EXE[parent::ENS/@REFCONTRAT=current()/@REFCONTRAT]"/>
    </xsl:copy>

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 71
    Points : 77
    Points
    77
    Par défaut
    Merci pour ta réponse.

    Effectivement, cela fonctionne bien mieux ainsi

    Une dernière question :

    En fait, mon flux réel est un peu plus complexe que celui que j'ai mis en exemple.

    En fait cela ressemble plus à ça :

    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
     
    <?xml version="1.0" encoding="UTF-8"?>
    <FICHIER>
      <STM>
     
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
      <!-- Les balises qui font l'objet de ma question -->
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
      <BALISE1 ATTR1="x" ATTR2="y" />
      <BALISE2 ATTR1="x" ATTR2="y" />
      <BALISE3 ATTR1="x" ATTR2="y" />
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
     
      <ENS REFCONTRAT="X">
        <EXE ANNEE="2005">
          <CRE MNDETCRE="15EUR" />
        </EXE>
      </ENS>
      <ENS REFCONTRAT="X">
        <EXE ANNEE="2006">
          <CRE MNDETCRE="15EUR" />
        </EXE>
      </ENS>
      <ENS REFCONTRAT="Y">
        <EXE ANNEE="2006">
          <CRE MNDETCRE="30EUR" />
        </EXE>
      </ENS>
      <STM>
    <FICHIER>
    Pour les balises que j'ai mises en évidence dans cet exemple, y a-t-il un moyen simple, en XSL, pour dire :
    Tous ceux qui ne font l'objet d'un template spécial, faut copier à l'identique
    car mis à part le regroupement sur les balises <ENS>, le reste doit rester exactement pareil.

    Je ne voudrais pas passer pour une grosse feignasse mais bien que j'ai lu pas mal de cours et tutoriels, j'ai pas vraiment l'impression d'être capable de faire un truc optimisé. Je crois qu'une bonne partie de la subtilité du XSL m'échappe.

    D'avance, merci de bien vouloir me consacrer un peu de temps pour m'aider.

    derek.mf

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 71
    Points : 77
    Points
    77
    Par défaut
    Bon, je pense avoir trouvé mais je suis pas sur que ma solution soit des plus élégantes (j'ai même l'impression que c'est plutôt bourrin mais ça a l'air de marcher !)

    Pour ceux que ça pourrait aider :

    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="group-by-ENS" match="ENS" use="@REFCONTRAT"/>  
     
      <xsl:template match="/"> 
      	<xsl:apply-templates />
    	<!-- <xsl:apply-templates select="STM" /> -->
    	<xsl:apply-templates 
    		select="ENS[generate-id(.)=generate-id(key('group-by-ENS',@REFCONTRAT)[1])]"/>      
      </xsl:template> 
     
      <xsl:template match="*">
      	<xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates />
        </xsl:copy>
      </xsl:template>
     
      <xsl:template match="ENS">
        <xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates select="//EXE[parent::ENS/@REFCONTRAT=current()/@REFCONTRAT]"/>
        </xsl:copy>
      </xsl:template>
     
      <xsl:template match="EXE">
        <xsl:copy-of select="."/>
      </xsl:template>
     
    </xsl:stylesheet>
    C'est dans ce bout de code là que je lui dis de tout copier à l'identique sauf ce pour quoi j'ai crée un template spécifique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    <xsl:template match="*">
      	<xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates />
        </xsl:copy>
      </xsl:template>
    Encore merci pour l'aide, ça m'a beaucoup aidé !

    @+

    derek.mf

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 71
    Points : 77
    Points
    77
    Par défaut Après vérification...
    Après vérification, donc, mon fichier XSL n'était pas bon mais j'ai finalement trouvé :

    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
     
    <?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"/>
     
    <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
    <!-- Déclaration de la clé qui va permettre de retrouver les ENS 	      -->
    <!-- semblables                                                           -->
    <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
    <xsl:key name="group-by-ENS" match="ENS" use="@REFCONTRAT"/>  
     
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
      <!-- Un template est prévu pour chaque balise inclus dans le document     -->
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
      <xsl:template match="/"> 
      	<xsl:apply-templates />
      </xsl:template> 
     
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
      <!-- Template pour toutes les balises qui doivent rester inchangés        -->
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
      <xsl:template match="FICHIER|STM|BALISE1|BALISE2|BALISE3|BALISE4|BALISE5|BALISE5|BALISE6">
      	<xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates />
        </xsl:copy>
      </xsl:template>
     
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
      <!-- Template pour l'élimination des doublons sur la balise ENS           -->
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
      <xsl:template match="ENS">
     
      	<!-- Création d'une clé permettant de retrouver toutes les balises ENS semblables -->
      	<!-- Pour chaque élément ENS trouvé, on récupère les EXE qui sont rattachés 	  -->
      	<!-- à un ENS similaire (ayant la même valeur dans l'attribut REFCONTRAT		  -->
      	<xsl:for-each
    		select="current()[generate-id(.)=generate-id(key('group-by-ENS',@REFCONTRAT)[1])]">
        	<xsl:copy>
              <xsl:copy-of select="@*"/>
              <xsl:apply-templates
    			select="//EXE[parent::ENS/@REFCONTRAT=current()/@REFCONTRAT]"/>
            </xsl:copy>
        </xsl:for-each>
     
      </xsl:template>
     
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
      <!-- On copie le contenu de chaque balise EXE et ses sous-balises			-->
      <!-- ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ -->
      <xsl:template match="EXE">
        <xsl:copy-of select="."/>
      </xsl:template>
     
    </xsl:stylesheet>
    Certes, je n'ai pas trouvé comment faire en sorte qu'il fasse de la bête copie pour tout ce qui n'est pas ENS ni EXE (j'ai pas trouvé comment faire un truc du genre <xsl:template match="not ENS">) mais cela fonctionne.

    @+

    derek.mf

  6. #6
    Rédacteur

    Avatar de Erwy
    Homme Profil pro
    Développeur Web
    Inscrit en
    Novembre 2003
    Messages
    4 967
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Points : 10 927
    Points
    10 927
    Par défaut
    Citation Envoyé par derek.mf

    Certes, je n'ai pas trouvé comment faire en sorte qu'il fasse de la bête copie pour tout ce qui n'est pas ENS ni EXE (j'ai pas trouvé comment faire un truc du genre <xsl:template match="not ENS">) mais cela fonctionne.
    simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:template match="*[name()!='ENS']">)

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

Discussions similaires

  1. [XSLT]Regroupement par attribut.
    Par zserdtfg dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 08/12/2006, 11h35
  2. [XSLT] regrouper des noeuds identiques
    Par DelphLaga dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 14/11/2006, 17h07
  3. [XSLT] Regrouper les noeuds qui se ressemblent
    Par yos dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 19/10/2006, 16h51
  4. [XSLT] Regroupement ds XML
    Par Virginie dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 19/10/2006, 12h35
  5. [XSLT] Regroupement en utilsant xsl:key
    Par AVRAVR dans le forum XSL/XSLT/XPATH
    Réponses: 5
    Dernier message: 28/07/2006, 10h02

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