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] Aplatir un XML (Structure arborescente => Structure linéaire)


Sujet :

XSL/XSLT/XPATH XML

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2006
    Messages
    857
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Septembre 2006
    Messages : 857
    Par défaut [XSLT] Aplatir un XML (Structure arborescente => Structure linéaire)
    Bonjour,

    Je voudrais transformer une structure arborescente en structure linéaire.
    Pour faire simple, partant d'un XML ayant une structure du style:

    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
     
    ROOT
      |--S1
      |    |--E1
      |    |    |--B1
      |    |    |--B2
      |    |--E2
      |    |    |--B3
      |    |    |--B4
      |--S2
      |    |--E3
      |    |    |--B5
      |    |    |--B6
      |    |    |--B7
      |    |--E4
      |    |    |--B8
    J'aimerais obtenir un XML "aplati" du style

    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
     
    ROOT
      |--S1
      |    |--E1
      |    |--B1
      |--S1
      |    |--E1
      |    |--B2
      |--S1
      |    |--E2
      |    |--B3
      |--S1
      |    |--E2
      |    |--B4
      |--S2
      |    |--E3
      |    |--B5
      |--S2
      |    |--E3
      |    |--B6
      |--S2
      |    |--E3
      |    |--B7
      |--S3
      |    |--E4
      |    |--B8
    En gros, ne conserver que la racine de premier niveau et "écraser" tout le reste.
    Ceci étant rendu plus difficile, sachant que je ne connais pas la structure de mon XML et ne connait pas non plus le nom de mes élèments...

    Etant débutant, merci de me dire si cela est rééllement possible et me donner des pistes le cas échéant.

    Merci d'avance.

  2. #2
    Expert confirmé
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 55

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

    Citation Envoyé par SONY30
    En gros, ne conserver que la racine de premier niveau et "écraser" tout le reste.
    Ca semble un peu plus compliqué que cela, il y a aussi une "factorisation" avec les éléments fils des éléments de premier niveau.

    Si je me base sur l'exemple que tu as donné, ceci devrait faire l'affaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        <xsl:template match="/*">
            <xsl:copy>
                <xsl:for-each select="*/*/*">
                    <xsl:element name="{name(../..)}">
                        <xsl:element name="{name(..)}"/>
                        <xsl:copy-of select="."/>                    
                    </xsl:element>
                </xsl:for-each>
            </xsl:copy>
        </xsl:template>
    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

  3. #3
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2006
    Messages
    857
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Septembre 2006
    Messages : 857
    Par défaut
    Le "souci" c'est que je ne connais pas la profondeur de mon XML.

    Mon besoin initial était de transformer ce style de XML là en tableau HTML, j'arrive à obtenir un HTML (1-n)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    S1---E1---B1
    -----------B2
    -----E2---B3
    -----------B4
    alors que je souhaiterais obtenir un HTML (n-n)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    S1---E1---B1
    S1---E1---B2
    S1---E2---B3
    S1---E2---B4
    Alors je m'étais dit (à tort ?) qu'il était peut-être plus facile de faire cela en plusieurs étapes, une première transformation qui m'aplati mon XML puis une deuxième qui me le traduit en HTML.
    Qu'en pensez-vous ?

  4. #4
    Membre Expert Avatar de alain.couthures
    Profil pro
    Gérant
    Inscrit en
    Avril 2007
    Messages
    902
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Gérant

    Informations forums :
    Inscription : Avril 2007
    Messages : 902
    Par défaut
    Bonjour,

    Voici ce que je propose comme feuille de style :
    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
    <xsl:stylesheet version="1.0" txs:name="aplati">
      <xsl:template match="/">
       <xsl:for-each select="*">
        <xsl:element name="{name()}">
         <xsl:for-each select="@*">
          <xsl:copy/>
         </xsl:for-each>
         <xsl:apply-templates/>
        </xsl:element>
       </xsl:for-each>
      </xsl:template>
      <xsl:template match="*[count(*)=0]">
       <xsl:call-template name="aplati">
        <xsl:with-param name="p" select="count(ancestor::*) - 1"/>
       </xsl:call-template>
      </xsl:template>
      <xsl:template name="aplati">
       <xsl:param name="p"/>
       <xsl:choose>
        <xsl:when test="$p = 0">
         <xsl:copy-of select="."/>
        </xsl:when>
        <xsl:otherwise>
         <xsl:variable name="aname">
          <xsl:for-each select="ancestor::*[position()=$p]">
           <xsl:value-of select="name()"/>
          </xsl:for-each>
         </xsl:variable>
         <xsl:element name="{$aname}">
          <xsl:for-each select="ancestor::*[position()=$p]/@*">
           <xsl:copy/>
          </xsl:for-each>
          <xsl:call-template name="aplati">
           <xsl:with-param name="p" select="$p - 1"/>
          </xsl:call-template>
         </xsl:element>
        </xsl:otherwise>
       </xsl:choose>
      </xsl:template>
     </xsl:stylesheet>
    (testé avec tXs : http://www.agencexml.com/txs/fr)

    Le principe est de chercher toutes les feuilles de l'arbre et de créer une branche de tous les ancêtres sauf la racine.

  5. #5
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2006
    Messages
    857
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Septembre 2006
    Messages : 857
    Par défaut
    Cela fonctionne très bien pour des éléments racine, mais va multiplier les lignes pour les éléments text.
    De plus je voudrais répéter les éléments text pour chaque ligne.

    Prenons le XML suivant
    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
    <S1>
      <lib>Structure 1</lib>
      <E1>
        <SEC1>
          <type>Type 1</type>
          <B1>
            <lib>Budget 1</lib>
          </B1>
          <B2>
            <lib>Budget 2</lib>
          </B2>
        </SEC1>
      </E1>
      <E2>
        <SEC1>
          <type>Type 2</type>
          <B1>
            <lib>Budget 3</lib>
          </B1>
          <B2>
            <lib>Budget 4</lib>
          </B2>
        </SEC1>
      </E2>
    </S1>
    <S2>
      <lib>Structure 2</lib>
      <E3>
        <SEC1>
          <type>Type 1</type>
          <B5>
            <lib>Budget 5</lib>
          </B5>
          <B6>
            <lib>Budget 6</lib>
          </B6>
          <B7>
            <lib>Budget 7</lib>
          </B7>
        </SEC1>
      </E3>
      <E4>
        <SEC1>
          <type>Type 2</type>
          <B8>
            <lib>Budget 8</lib>
          </B8>
        </SEC1>
      </E4>
    </S2>
    Je souhaiterais obtenir le XML suivant
    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
    <ROOT>
    <S1>
      <lib>Structure 1</lib>
      <type>Type 1</type>
      <libb>Budget 1</libb>
    </S1>
    <S1>
      <lib>Structure 1</lib>
      <type>Type 1</type>
      <libb>Budget 2</libb>
    </S1>
    <S1>
      <lib>Structure 1</lib>
      <type>Type 2</type>
      <libb>Budget 3</libb>
    </S1>
    <S1>
      <lib>Structure 1</lib>
      <type>Type 2</type>
      <libb>Budget 4</libb>
    </S1>
    <S2>
      <lib>Structure 2</lib>
      <type>Type 1</type>
      <libb>Budget 5</libb>
    </S2>
    <S2>
      <lib>Structure 2</lib>
      <type>Type 1</type>
      <libb>Budget 6</libb>
    </S2>
    <S2>
      <lib>Structure 2</lib>
      <type>Type 1</type>
      <libb>Budget 7</libb>
    </S2>
    <S2>
      <lib>Structure 2</lib>
      <type>Type 2</type>
      <libb>Budget 8</libb>
    </S2>
    </ROOT>

  6. #6
    Membre Expert Avatar de alain.couthures
    Profil pro
    Gérant
    Inscrit en
    Avril 2007
    Messages
    902
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Gérant

    Informations forums :
    Inscription : Avril 2007
    Messages : 902
    Par défaut
    OK, je comprends mieux : il faut "ramasser" les valeurs textes présentes dans les ancêtres.

    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
    <xsl:stylesheet version="1.0" txs:name="aplati">
      <xsl:template match="/">
       <xsl:for-each select="*">
        <xsl:element name="{name()}">
         <xsl:for-each select="@*">
          <xsl:copy/>
         </xsl:for-each>
         <xsl:apply-templates mode="aplat" select="//*[count(*)=0 and count(preceding-sibling::*[count(*)!=0])=0 and count(following-sibling::*[count(*)!=0])=0]"/>
        </xsl:element>
       </xsl:for-each>
      </xsl:template>
      <xsl:template match="*" mode="aplat">
       <xsl:call-template name="aplati">
        <xsl:with-param name="p" select="count(ancestor::*) - 1"/>
       </xsl:call-template>
      </xsl:template>
      <xsl:template name="aplati">
       <xsl:param name="p"/>
       <xsl:if test="$p != 0">
         <xsl:variable name="aname">
          <xsl:for-each select="ancestor::*[position()=$p]">
           <xsl:value-of select="name()"/>
          </xsl:for-each>
         </xsl:variable>
         <xsl:choose>
          <xsl:when test="$p = count(ancestor::*) -1">
           <xsl:element name="{$aname}">
            <xsl:for-each select="ancestor::*[position()=$p]/@*">
             <xsl:copy/>
            </xsl:for-each>
            <xsl:for-each select="ancestor::*[position()=$p]/*[count(*)=0 and text()!='']">
             <xsl:copy-of select="."/>
            </xsl:for-each>
            <xsl:call-template name="aplati">
             <xsl:with-param name="p" select="$p - 1"/>
            </xsl:call-template>
           </xsl:element>
          </xsl:when>
          <xsl:otherwise>
           <xsl:for-each select="ancestor::*[position()=$p]/*[count(*)=0 and text()!='']">
            <xsl:copy-of select="."/>
           </xsl:for-each>
           <xsl:call-template name="aplati">
            <xsl:with-param name="p" select="$p - 1"/>
           </xsl:call-template>
          </xsl:otherwise>
         </xsl:choose>
       </xsl:if>
      </xsl:template>
     </xsl:stylesheet>
    (testé avec http://www.agencexml.com/txs/fr)

Discussions similaires

  1. [XSLT] Gros souci de tri sur structure arborescente
    Par stujava dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 25/03/2010, 17h49
  2. [C#] Structure arborescente. Construire un arbre d'Object.
    Par PerpetualSnow dans le forum Windows Forms
    Réponses: 1
    Dernier message: 30/08/2006, 13h57
  3. Structure arborescente et STL
    Par Thomus38 dans le forum SL & STL
    Réponses: 2
    Dernier message: 27/11/2005, 17h44
  4. [xml]Conversion d'une structure xml en csv
    Par cchatel2000 dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 01/08/2005, 16h00
  5. Coherence dans les structures arborescentes...
    Par Alec6 dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 29/09/2004, 12h04

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