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

  1. #21
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2006
    Messages
    857
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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
    Points : 884
    Points
    884
    Par défaut
    Cela fonctionne bien, j'ai réussi à intégrer mes spécificités (tri, pagination, javascript, mise en page) sans problèmes.

    Par contre concernant la première transformation (post n°9) une spécificité de mon XML pose problème. Si j'ai un noeud de regroupement d'information (<adresse> dans l'exemple ci-dessous), il me retourne 2 lignes au lieu d'une seule.
    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
    <ROOT>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Séb</Libelle-de-la-structure>
      <adresse>
      	<cp>34000</cp>
      	<distrib>Montpellier</distrib>
      </adresse>
      <exercice>
      	<annee>2006</annee>
      	<section>
      		<type>H</type>
      		<budget>
      			<lib>Budget Séb</lib>
      			<t>B</t>
      		</budget>
      	</section>
      </exercice>
    </Structure>
    </ROOT>
    En rajoutant cette condition dans le select ça fonctionne mais bon...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select="//*[count(*)=0 and count(preceding-sibling::*[count(*)=0])=0 and count(preceding-sibling::*[count(*)!=0])=0 and name(parent::*)!='adresse' and count(following-sibling::*[count(*)!=0])=0]"

  2. #22
    Membre éprouvé 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
    Points : 1 247
    Points
    1 247
    Par défaut
    En fait, il y a deux points à améliorer :
    • n'appliquer le template qu'aux feuilles les plus hautes (si on remet l'arbre debout!) et pour ça on rejoint le second algo
    • ramasser tous les sous-noeuds texte des ancètres par template

    Je m'y remets dès que j'ai le temps pour !

  3. #23
    Membre éprouvé 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
    Points : 1 247
    Points
    1 247
    Par défaut
    Voici une nouvelle version...
    Elle est à tester car elle comporte une restriction pour ne pas être trop compliquée : les noms des noeuds doivent être réguliers à une profondeur donnée, ce qui semble bien être le cas dans le dernier exemple fourni :
    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
    <xsl:stylesheet version="1.0" txs:name="aplati">
      <xsl:template match="/">
       <xsl:variable name="deepest">
        <xsl:for-each select="//*[count(*)=0]">
         <xsl:sort select="count(ancestor::*)" order="descending"/>
         <xsl:if test="position() = 1">
          <xsl:value-of select="count(ancestor::*)"/>
         </xsl:if>
        </xsl:for-each>
       </xsl:variable>
       <xsl:for-each select="*">
        <xsl:element name="{name()}">
         <xsl:for-each select="@*">
          <xsl:copy/>
         </xsl:for-each>
         <xsl:apply-templates mode="aplat" select="//*[count(ancestor::*)=$deepest and count(*)=0 and count(preceding-sibling::*[count(*)=0])=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:variable name="next" select="name(ancestor::*[position()=$p - 1])"/>
        <xsl:choose>
         <xsl:when test="$p = 1">
          <xsl:copy-of select="ancestor::*[1]/*[text()!='']"/>
         </xsl:when>
         <xsl:when test="$p = count(ancestor::*) -1">
          <xsl:element name="{name(ancestor::*[position()=$p])}">
           <xsl:copy-of select="ancestor::*[position()=$p]/@*"/>
           <xsl:apply-templates mode="ramasse" select="ancestor::*[position()=$p]/*[name() != $next]"/>
           <xsl:call-template name="aplati">
            <xsl:with-param name="p" select="$p - 1"/>
           </xsl:call-template>
          </xsl:element>
         </xsl:when>
         <xsl:otherwise>
          <xsl:apply-templates mode="ramasse" select="ancestor::*[position()=$p]/*[name() != $next]"/>
          <xsl:call-template name="aplati">
           <xsl:with-param name="p" select="$p - 1"/>
          </xsl:call-template>
         </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
      <xsl:template match="*" mode="ramasse">
       <xsl:choose>
        <xsl:when test="count(*)=0 and text()!=''">
         <xsl:copy-of select="."/>
        </xsl:when>
        <xsl:when test="count(*)!=0">
         <xsl:apply-templates select="*" mode="ramasse"/>
        </xsl:when>
       </xsl:choose>
      </xsl:template>
     </xsl:stylesheet>

  4. #24
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2006
    Messages
    857
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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
    Points : 884
    Points
    884
    Par défaut
    Il faut que la profondeur max des éléments text soit la même pour toutes les lignes.
    Il arrive à gérer ce 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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <ROOT>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Séb</Libelle-de-la-structure>
      <adresse>
      	<cp>34000</cp>
      	<distrib>Montpellier</distrib>
      </adresse>
      <exercice>
      	<annee>2006</annee>
      	<section>
      		<type>H</type>
      		<budget>
      			<lib>Budget Séb</lib>
      			<t>B</t>
      		</budget>
      	</section>
      </exercice> 
    </Structure>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Tib</Libelle-de-la-structure>
      <exercice>
      	<annee>2006</annee>
      	<section>
      		<type>H</type>
      		<budget>
      			<lib>Budget Tib</lib>
      			<t>B</t>
      		</budget>
      	</section>
      </exercice>  
    </Structure>
    </ROOT>
    Mais pas celui-ci pour lequel il fait sauter une ligne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <ROOT>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Séb</Libelle-de-la-structure>
      <adresse>
      	<cp>34000</cp>
      	<distrib>Montpellier</distrib>
      </adresse>
    </Structure>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Tib</Libelle-de-la-structure>
    </Structure>
    </ROOT>

  5. #25
    Membre éprouvé 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
    Points : 1 247
    Points
    1 247
    Par défaut
    Bon, ça devient de plus en plus hard !

    Mais pas encore désespéré, il suffit de descendre le traitement à chaque enfant de la racine...
    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
     <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:for-each select="*">
          <xsl:variable name="deepest">
           <xsl:for-each select="descendant::*[count(*)=0]">
            <xsl:sort select="count(ancestor::*)" order="descending"/>
            <xsl:if test="position() = 1">
             <xsl:value-of select="count(ancestor::*)"/>
            </xsl:if>
           </xsl:for-each>
          </xsl:variable>
          <xsl:apply-templates mode="aplat" select="//*[count(ancestor::*)=$deepest and count(*)=0 and count(preceding-sibling::*[count(*)=0])=0 and count(preceding-sibling::*[count(*)!=0])=0 and count(following-sibling::*[count(*)!=0])=0]"/>
         </xsl:for-each>
        </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:variable name="next" select="name(ancestor::*[position()=$p - 1])"/>
        <xsl:choose>
         <xsl:when test="$p = count(ancestor::*) -1">
          <xsl:element name="{name(ancestor::*[position()=$p])}">
           <xsl:copy-of select="ancestor::*[position()=$p]/@*"/>
           <xsl:apply-templates mode="ramasse" select="ancestor::*[position()=$p]/*[name() != $next]"/>
           <xsl:if test="$p != 1">
            <xsl:call-template name="aplati">
             <xsl:with-param name="p" select="$p - 1"/>
            </xsl:call-template>
           </xsl:if>
          </xsl:element>
         </xsl:when>
         <xsl:when test="$p = 1">
          <xsl:copy-of select="ancestor::*[1]/*[text()!='']"/>
         </xsl:when>
         <xsl:otherwise>
          <xsl:apply-templates mode="ramasse" select="ancestor::*[position()=$p]/*[name() != $next]"/>
          <xsl:call-template name="aplati">
           <xsl:with-param name="p" select="$p - 1"/>
          </xsl:call-template>
         </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
      <xsl:template match="*" mode="ramasse">
       <xsl:choose>
        <xsl:when test="count(*)=0 and text()!=''">
         <xsl:copy-of select="."/>
        </xsl:when>
        <xsl:when test="count(*)!=0">
         <xsl:apply-templates select="*" mode="ramasse"/>
        </xsl:when>
       </xsl:choose>
      </xsl:template>
     </xsl:stylesheet>
    Au passage, j'ai corrigé un bug sur la gestion du cas particulier de profondeur 2.

    Cette feuille de style rajoute une contrainte supplémentaire: la profondeur max doit être identique pour chaque sous-noeud de la racine ou, sinon, on a un sous-noeud distinct.

  6. #26
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2006
    Messages
    857
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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
    Points : 884
    Points
    884
    Par défaut
    Désolé...

    Cela fonctionne maintenant sur ce cas

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <ROOT>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Séb</Libelle-de-la-structure>
      <adresse>
      	<cp>34000</cp>
      	<distrib>Montpellier</distrib>
      </adresse>
    </Structure>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Tib</Libelle-de-la-structure>
    </Structure>
    </ROOT>
    mais plus sur celui-là

    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
    <ROOT>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Séb</Libelle-de-la-structure>
      <adresse>
      	<cp>34000</cp>
      	<distrib>Montpellier</distrib>
      </adresse>
      <exercice>
      	<annee>2006</annee>
      	<section>
      		<type>H</type>
      		<budget>
      			<lib>Budget Séb</lib>
      			<t>B</t>
      		</budget>
      	</section>
      </exercice> 
    </Structure>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Tib</Libelle-de-la-structure>
      <exercice>
      	<annee>2006</annee>
      	<section>
      		<type>H</type>
      		<budget>
      			<lib>Budget Tib</lib>
      			<t>B</t>
      		</budget>
      	</section>
      </exercice>  
    </Structure>
    </ROOT>
    ni sur celui là pour lequel il fait un produit cartésien

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <ROOT>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Séb</Libelle-de-la-structure>
    </Structure>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Tib</Libelle-de-la-structure>
    </Structure>
    </ROOT>

  7. #27
    Membre éprouvé 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
    Points : 1 247
    Points
    1 247
    Par défaut
    J'ai encore la joue toute rouge de la baffe que je viens de me mettre... Je suis trop étourdi : il ne faut plus utiliser "//" mais "descendant::" et j'avais oublié de reporter cette modification dans l'apply-templates :
    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
     <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:for-each select="*">
          <xsl:variable name="deepest">
           <xsl:for-each select="descendant::*[count(*)=0]">
            <xsl:sort select="count(ancestor::*)" order="descending"/>
            <xsl:if test="position() = 1">
             <xsl:value-of select="count(ancestor::*)"/>
            </xsl:if>
           </xsl:for-each>
          </xsl:variable>
          <xsl:apply-templates mode="aplat" select="descendant::*[count(ancestor::*)=$deepest and count(*)=0 and count(preceding-sibling::*[count(*)=0])=0 and count(preceding-sibling::*[count(*)!=0])=0 and count(following-sibling::*[count(*)!=0])=0]"/>
         </xsl:for-each>
        </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:variable name="next" select="name(ancestor::*[position()=$p - 1])"/>
        <xsl:choose>
         <xsl:when test="$p = count(ancestor::*) -1">
          <xsl:element name="{name(ancestor::*[position()=$p])}">
           <xsl:copy-of select="ancestor::*[position()=$p]/@*"/>
           <xsl:apply-templates mode="ramasse" select="ancestor::*[position()=$p]/*[name() != $next]"/>
           <xsl:if test="$p != 1">
            <xsl:call-template name="aplati">
             <xsl:with-param name="p" select="$p - 1"/>
            </xsl:call-template>
           </xsl:if>
          </xsl:element>
         </xsl:when>
         <xsl:when test="$p = 1">
          <xsl:copy-of select="ancestor::*[1]/*[text()!='']"/>
         </xsl:when>
         <xsl:otherwise>
          <xsl:apply-templates mode="ramasse" select="ancestor::*[position()=$p]/*[name() != $next]"/>
          <xsl:call-template name="aplati">
           <xsl:with-param name="p" select="$p - 1"/>
          </xsl:call-template>
         </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
      <xsl:template match="*" mode="ramasse">
       <xsl:choose>
        <xsl:when test="count(*)=0 and text()!=''">
         <xsl:copy-of select="."/>
        </xsl:when>
        <xsl:when test="count(*)!=0">
         <xsl:apply-templates select="*" mode="ramasse"/>
        </xsl:when>
       </xsl:choose>
      </xsl:template>
     </xsl:stylesheet>

  8. #28
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2006
    Messages
    857
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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
    Points : 884
    Points
    884
    Par défaut
    Chapeau l'artiste

    Juste une dernière question pour la route
    J'ai intégré dans le XSL permettant de transformer mon XML à plat en tableau HTML, un tri. Ce tri ne fonctionnant pas sur les dates j'ai donc conditionné ma boucle <for-each> c'est vraiment pas terrible mais ça marche, à première vu comme ça, est-il faisable de faire plus propre ?

    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:template match="/">
      <table>
       <xsl:for-each select="/root/*">
        <xsl:sort select="count(*[not(@visible) and name()!='ID'])" order="descending"/>
        <xsl:if test="position()=1">
         <xsl:variable name="lemax" select="."/>
     
    	<xsl:choose>
    	<xsl:when test="contains(*/*[name()=$champTri],'/')">     
     
         <xsl:for-each select="/root/*">
          <xsl:sort select="concat(substring(*[name()=$champTri],7,4), substring(*[name()=$champTri],4,2), substring(*[name()=$champTri],1,2))" order="{$sensTri}"/>
          <xsl:variable name="cur" select="."/>
          <tr>
           <xsl:for-each select="$lemax/*">
            <xsl:variable name="n" select="name()"/>
            <xsl:if test="not(@visible)">
            <td>
             <xsl:value-of select="$cur/*[name()=$n]"/>
            </td>
            </xsl:if>
           </xsl:for-each>
          </tr>
         </xsl:for-each>
     
        </xsl:when>
        <xsl:otherwise>
     
         <xsl:for-each select="/root/*">
          <xsl:sort select="*[name()=$champTri]" order="{$sensTri}"/>
          <xsl:variable name="cur" select="."/>
          <tr>
           <xsl:for-each select="$lemax/*">
            <xsl:variable name="n" select="name()"/>
            <xsl:if test="not(@visible)">
            <td>
             <xsl:value-of select="$cur/*[name()=$n]"/>
            </td>
            </xsl:if>
           </xsl:for-each>
          </tr>
         </xsl:for-each>
     
        </xsl:otherwise>
        </xsl:choose>
     
        </xsl:if>
       </xsl:for-each>
      </table>
     </xsl:template>
    Encore merci et bravo , si je peux vous être utile pour quoique ce soit, n'hésitez pas.

  9. #29
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    Bonjour à tous, depuis une petite heure, je suis en train de me battre à aplatir un arbre, mais je n'y arrive jamais totalement.

    Il faut que je passe de ç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
    31
    32
    33
    <?xml version="1.0" encoding="ISO-8859-1"?> 
     
    <a v="a1">
     
    	<b v="b1">
     
    		<c v="c1"></c>
     
    		<c v="c2"></c>
     
    	</b>
     
    	<b v="b2">
     
    		<c v="c3"></c>
     
    	</b>
     
    	<b v="b3">
     
    		<c v="c4"></c>
     
    		<c v="c5"></c>
     
    	</b>
     
    	<b v="b4">
     
    		<c v="c6"></c>
     
    	</b>
     
    </a>
    à ç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
    <?xml version="1.0" encoding="ISO-8859-1"?> 
     
    <a v="a1"></a>
     
    <b v="b1"></b>
     
    <c v="c1"></c>
     
    <c v="c2"></c>
     
    <b v="b2"></b>
     
    <c v="c3"></c>
     
    <b v="b3"></b>
     
    <c v="c4"></c>
     
    <c v="c5"></c>
     
    <b v="b4"></b>
     
    <c v="c6"></c>
    Avec 3 templates, j'arrive à récupérer les 3 séparément, mais jamais ensembles.

    Merci de votre aide, @+

  10. #30
    Membre éprouvé 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
    Points : 1 247
    Points
    1 247
    Par défaut
    Le résultat souhaité n'est pas un document bien formé car il n'a pas de racine : il s'agit d'un fragment... Est-ce vraiment ce que vous souhaitez ?

    Voilà une transformation avec racine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     <xsl:stylesheet version="1.0" txs:name="casse">
      <xsl:template match="/">
       <root>
        <xsl:apply-templates/>
       </root>
      </xsl:template>
      <xsl:template match="@*|*">
       <xsl:copy>
        <xsl:apply-templates select="@*"/>
       </xsl:copy>
       <xsl:apply-templates/>
      </xsl:template>
     </xsl:stylesheet>

  11. #31
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    Oui, c'est le parcours en profondeur d'un arbre.

    J'te remercie.

    @+

  12. #32
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2006
    Messages
    857
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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
    Points : 884
    Points
    884
    Par défaut
    Me revoilà 3 mois après...

    Le XSL proposé par Alain me pose un problème si j'ai plusieurs racines de même profondeur maximale, il me double la ligne de résultat...



    Edit : la racine la plus profonde ne doit pas être la référence.
    L'évènement déclencheur de la création d'une nouvelle ligne, sera la présence de racines qui ont des frères.

    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
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="ISO-8859-1" indent="yes"/>
     
      <xsl:template match="/">
       <!-- Pour le noeud racine -->
       <xsl:for-each select="*">
        <!-- Copie des attributs -->
        <xsl:element name="{name()}">
         <xsl:for-each select="@*">
          <xsl:copy/>
         </xsl:for-each>
         <!-- Pour chaque noeud fils -->
         <xsl:for-each select="*">
          <!-- RECUPERATION PROFONDEUR MAXIMALE -->
          <xsl:variable name="deepest">
           <!-- Pour tous les descendants qui n'ont pas de fils -->
           <xsl:for-each select="descendant::*[count(*)=0]">
            <!-- Trié par ordre décroissant -->
            <xsl:sort select="count(ancestor::*)" order="descending"/>
            <!-- Je récupère le premier (le plus profond) -->
            <xsl:if test="position() = 1">
             <xsl:value-of select="count(ancestor::*)"/>
            </xsl:if>
           </xsl:for-each>
          </xsl:variable>
          <!-- FIN RECUPERATION PROFONDEUR MAXIMALE -->
          <xsl:apply-templates mode="aplat" select="descendant::*[count(ancestor::*)=$deepest and count(*)=0 and count(preceding-sibling::*[count(*)=0])=0 and count(preceding-sibling::*[count(*)!=0])=0 and count(following-sibling::*[count(*)!=0])=0]"/>
         </xsl:for-each>
        </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:variable name="next" select="name(ancestor::*[position()=$p - 1])"/>
        <xsl:choose>
         <xsl:when test="$p = count(ancestor::*) -1">
          <xsl:element name="{name(ancestor::*[position()=$p])}">
           <xsl:copy-of select="ancestor::*[position()=$p]/@*"/>
           <xsl:apply-templates mode="ramasse" select="ancestor::*[position()=$p]/*[name() != $next]"/>
           <xsl:if test="$p != 1">
            <xsl:call-template name="aplati">
             <xsl:with-param name="p" select="$p - 1"/>
            </xsl:call-template>
           </xsl:if>
          </xsl:element>
         </xsl:when>
         <xsl:when test="$p = 1">
          <xsl:copy-of select="ancestor::*[1]/*[text()!='']"/>
         </xsl:when>
         <xsl:otherwise>
          <xsl:apply-templates mode="ramasse" select="ancestor::*[position()=$p]/*[name() != $next]"/>
          <xsl:call-template name="aplati">
           <xsl:with-param name="p" select="$p - 1"/>
          </xsl:call-template>
         </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
     
      <xsl:template match="*" mode="ramasse">
       <xsl:choose>
        <!--<xsl:when test="count(*)=0 and text()!=''">-->
        <xsl:when test="count(*)=0">
         <xsl:copy-of select="."/>
        </xsl:when>
        <xsl:when test="count(*)!=0">
         <xsl:apply-templates select="*" mode="ramasse"/>
        </xsl:when>
       </xsl:choose>
      </xsl:template>
     
    </xsl:stylesheet>
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <ROOT>
    <Structure>
      <ID>|D_STRUCT070000000001|1|</ID>
      <Libelle-de-la-structure>Séb</Libelle-de-la-structure>
      <adresse>
        <cp>34000</cp>
        <distrib>Montpellier</distrib>
      </adresse>
      <exercice>
        <annee>2006</annee>
        <section>
          <type>H</type>
          <budget>
            <lib>Budget Séb</lib>
            <t>B</t>
          </budget>
        </section>
      </exercice> 
      <racine>
        <test>
          <retest>
            <lib>TEST</lib>
          </retest>
        </test>    
      </racine>  
    </Structure>
    </ROOT>

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