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

XML/XSL et SOAP Discussion :

hiérarchisation sous deux noeuds parents créés en fonction de noeuds enfants


Sujet :

XML/XSL et SOAP

  1. #1
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2022
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2022
    Messages : 3
    Points : 3
    Points
    3
    Par défaut hiérarchisation sous deux noeuds parents créés en fonction de noeuds enfants
    Bonjour,
    je débute en XML et XSLT et j'ai besoin d'écrire une transformation qui semble bien plus difficile que je ne l'imaginais.
    J'ai créé un fichier xml à partir d'un tableur et j'ai besoin de hiérarchiser les élements "row" de mon fichier xml sous deux noeuds parents créés selon des éléments enfant ("catalog" et "series", "catalog" étant le parent de "series", et "series" parent de "row"). Dans un second temps, j'aimerais donner des attributs à mes noeuds parent nouvellement créés.
    Voici une partie simplifiée des fichiers xml de départ et le fichier xml tel que je le souhaiterais.

    XML INPUT FILE

    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"?>
    <root>
       <row>
           <year>1999</year>
           <name>name1</name>
           <catalog>catalogA</catalog>
           <series>seriesA</series>
       </row>
       <row>
           <year>2000</year>
           <name>name2</name>
           <catalog>catalogA</catalog>
           <series>seriesB</series>
       </row>
       <row>
           <year>2001</year>
           <name>name3</name>
           <catalog>catalogB</catalog>
           <series>seriesA</series>
       </row>
       <row>
           <year>2002</year>
           <name>name4</name>
           <catalog>catalogB</catalog>
           <series>seriesB</series>
       </row>
       <row>
           <year>2003</year>
           <name>name5</name>
           <catalog>catalogA</catalog>
           <series>seriesA</series>
       </row>
    </root>
    XML OUTPUT FILE

    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
     
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
       <catalog id="catalogA">
           <series id="seriesA">
               <row>
                   <year>1999</year>
                   <name>name1</name>
                   <catalog>catalogA</catalog>
                   <series>seriesA</series>
               </row>
               <row>
                   <year>2003</year>
                   <name>name5</name>
                   <catalog>catalogA</catalog>
                   <series>seriesA</series>
               </row>
           </series>
           <series id="seriesB">
               <row>
                   <year>2000</year>
                   <name>name2</name>
                   <catalog>catalogA</catalog>
                   <series>seriesB</series>
               </row>
           </series>
       </catalog>
       <catalog id="catalogB">
           <series id="seriesA">
               <row>
                   <year>2001</year>
                   <name>name3</name>
                   <catalog>catalogB</catalog>
                   <series>seriesA</series>
               </row>
           </series>
           <series id="seriesB">
               <row>
                   <year>2002</year>
                   <name>name4</name>
                   <catalog>catalogB</catalog>
                   <series>seriesB</series>
               </row>
           </series>
       </catalog>
    </root>
    J'ai essayé différentes choses, mais je ne parviens pas à formuler des instructions convenables ni à les placer dans le bon ordre. Tout ce que j'ai pu faire, c'est ce fichier xsl qui ne semble pas fonctionner...

    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:template match="/">
    <root>
    <xsl:for-each select="/root/row/catalog">
    <catalog>
    <xsl:attribute name="id"><xsl:value-of select="./root/row/@IsMulti"/></xsl:attribute>
    <xsl:for-each select="./root/row/series">
    <series>
    <xsl:attribute name="id"><xsl:value-of select="./root/row/@IsMulti"/></xsl:attribute>
    <xsl:for-each select="./root/row">
    <row>
    <year>
    <xsl:value-of   select="./year"/>
    </year>
    <name>
    <xsl:value-of   select="./name"/>
    </name>
    <catalog>
    <xsl:value-of   select="."/>
    </catalog>
    <series>
    <xsl:value-of   select="."/>
    </series>
    </row>
    </xsl:for-each>
    </series>
    </xsl:for-each>
    </catalog>
    </xsl:for-each>
    </root>
    </xsl:template>
    </xsl:stylesheet>
    Pouvez-vous m'aider à obtenir ces transformations?

  2. #2
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    On sait très bien que ce genre de problème de groupement se répète, ça reste un pas assez difficile à franchir pour des débutants et même pour des initiés. Je pense il faut savoir le faire en xslt 1.0 avant tout pour le maîtriser. Voici comment faire à ma façon un peu spontanément.
    Code xslt1 : 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
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" />
    <xsl:key name="cat-group" match="row" use="normalize-space(catalog)" />
    <xsl:key name="cat-series-group" match="row" use="concat(normalize-space(catalog),'---', normalize-space(series))" />
     
    <xsl:template match="/root">
        <root>
            <xsl:apply-templates select="row[generate-id()=generate-id(key('cat-group', normalize-space(catalog))[1])]" mode="cat" />
        </root>
    </xsl:template>
     
    <xsl:template match="row" mode="cat">
        <xsl:variable name="cat" select="normalize-space(catalog)" />
        <xsl:element name="catalog">
            <xsl:attribute name="id">
                <xsl:value-of select="$cat" />
            </xsl:attribute>
            <xsl:apply-templates select="parent::*/row[generate-id()=generate-id(key('cat-series-group',concat($cat,'---',normalize-space(series)))[1])]" mode="series" />
        </xsl:element>
    </xsl:template>
     
    <xsl:template match="row" mode="series">
        <xsl:variable name="series" select="normalize-space(series)" />
        <xsl:element name="series">
            <xsl:attribute name="id">
                <xsl:value-of select="$series" />
            </xsl:attribute>
            <xsl:copy-of select="." />
        </xsl:element>
    </xsl:template>
     
    </xsl:stylesheet>

  3. #3
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2022
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2022
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Merci infiniment pour votre aide, tsuji.
    Grâce à votre code, la transformation est allée plus loin que jamais.
    La transformation fonctionne parfaitement sur l'extrait de fichier xml, mais lorsque je l'applique au fichier complet, un problème que je ne m'explique pas subsiste.
    Sur mon fichier complet (contenant plusieurs centaines d'éléments "row"), les noeuds parents se créent tous, avec la bonne hiérarchie, mais sous chaque noeud "series", on ne trouve jamais plus d'un seul élément "row".

    Autrement dit, au lieu d'avoir :

    catalog
    series
    row
    row
    row, etc.
    series
    row
    row
    row, etc.

    On obtient :

    catalog
    series
    row
    catalog
    series
    row

    J'ai essayé de placer des "xsl:for-each", dans l'espoir de "boucler" les opérations, mais il semble que je fasse fausse route.

    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
     
     
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" />
    <xsl:key name="cat-group" match="row" use="normalize-space(catalog)" />
    <xsl:key name="cat-series-group" match="row" use="concat(normalize-space(catalog),'---', normalize-space(series))" />
     
    <xsl:template match="/root">
        <root>
            <xsl:apply-templates select="row[generate-id()=generate-id(key('cat-group', normalize-space(catalog))[1])]" mode="cat" />
        </root>
    </xsl:template>
     
    <xsl:template match="row" mode="cat">
        <xsl:for-each select="root/row">
        <xsl:variable name="cat" select="normalize-space(catalog)" />
        <xsl:element name="catalog">
            <xsl:attribute name="id">
                <xsl:value-of select="$cat" />
            </xsl:attribute>
            <xsl:apply-templates select="parent::*/row[generate-id()=generate-id(key('cat-series-group',concat($cat,'---',normalize-space(series)))[1])]" mode="series" />
        </xsl:element>
    </xsl:for-each>
    </xsl:template>
     
    <xsl:template match="row" mode="series">
        <xsl:for-each select="root/row">
        <xsl:variable name="series" select="normalize-space(series)" />
        <xsl:element name="series">
            <xsl:attribute name="id">
                <xsl:value-of select="$series" />
            </xsl:attribute>
            <xsl:copy-of select="." />
        </xsl:element>
    </xsl:for-each>
    </xsl:template>
     
    </xsl:stylesheet>
    Y a-t-il un moyen de traiter l'ensemble des éléments "row"?

  4. #4
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    Modifiez mon template mode series comme suite.
    Code xslt 1.0 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <xsl:template match="row" mode="series">
        <xsl:variable name="series" select="normalize-space(series)" />
        <xsl:variable name="cat" select="normalize-space(catalog)" />
        <xsl:element name="series">
            <xsl:attribute name="id">
                <xsl:value-of select="$series" />
            </xsl:attribute>
            <xsl:for-each select="key('cat-series-group', concat($cat, '---', $series))">
                <xsl:copy-of select="." />
            </xsl:for-each>
        </xsl:element>
    </xsl:template>

  5. #5
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2022
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2022
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Le code fonctionne à merveille!
    Je vais l'étudier et essayer d'y ajouter d'autres transformations qui pourraient m'être utiles, comme par exemple ajouter un noeud parent "year" et classer les "row" selon les années au sein d'un même "series".
    Et étudier d'avantage les transformations xslt.
    Je vous remercie beaucoup pour votre aide précieuse.

  6. #6
    Membre émérite Avatar de tsuji
    Inscrit en
    Octobre 2011
    Messages
    1 558
    Détails du profil
    Informations forums :
    Inscription : Octobre 2011
    Messages : 1 558
    Points : 2 736
    Points
    2 736
    Par défaut
    Avec la façon de faire en xslt 1.0 bien comprise, voici comment faire en xslt 2.0 qui a le mérite d'être plus concis en apparence.
    Code xslt2 : 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
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" />
    <xsl:template match="/root">
        <root>
            <xsl:for-each-group select="row" group-by="catalog/normalize-space()">
                <catalog id="{current-grouping-key()}">
                    <xsl:for-each-group select="current-group()" group-by="series/normalize-space()">
                        <series id="{current-grouping-key()}">
                            <xsl:for-each select="current-group()">
                                <xsl:copy-of select="." />
                            </xsl:for-each>
                        </series>
                    </xsl:for-each-group>
                </catalog>
            </xsl:for-each-group>
        </root>
    </xsl:template>
    </xsl:stylesheet>
    Voilà maintenant vous savez tout.

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

Discussions similaires

  1. Comment savoir si deux noeuds ont un lien de parenté?
    Par alakauf dans le forum Composants
    Réponses: 4
    Dernier message: 28/07/2011, 11h16
  2. Soumettre deux formulaires dans la même fonction.
    Par Bisûnûrs dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 15/11/2006, 23h18
  3. Donnees sous deux tables
    Par salmoliv dans le forum Langage SQL
    Réponses: 2
    Dernier message: 08/03/2006, 14h17
  4. Deux librairies implémentant les mêmes fonctions ?
    Par gangsoleil dans le forum Linux
    Réponses: 3
    Dernier message: 26/01/2006, 10h37
  5. Réponses: 10
    Dernier message: 24/02/2004, 12h28

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