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 :

[XSL]Dupliquer un noeud


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 167
    Points : 69
    Points
    69
    Par défaut [XSL]Dupliquer un noeud
    Bonjour,

    J'essais de dupliquer le premier noeud sous la racine, en conservant les namespaces mais pas les valeurs.

    Exemple:
    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
     
    <xsd:root xmlns:xsd="monNamespace" xmlns:xsi="http://www.w3.org/2delegatedCn001/XMLSchema-instance" xsi:type="xsd:StrArray">
      <tns:value xmlns:tns="monNamespace">
      	<tns:code xmlns:tns="monNamespace">titi</tns:code>
      	<tns:message xmlns:tns="monNamespace">toto</tns:message>
      </tns:value>
      <tns:value xmlns:tns="monNamespace">
      	<tns:code xmlns:tns="monNamespace">tata</tns:code>
      	<tns:message xmlns:tns="monNamespace">tutu</tns:message>
      </tns:value>
    </xsd:root>
    Je veux que ça donne 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
     
    <xsd:root xmlns:xsd="monNamespace" xmlns:xsi="http://www.w3.org/2delegatedCn001/XMLSchema-instance" xsi:type="xsd:StrArray">
      <tns:value xmlns:tns="monNamespace">
      	<tns:code xmlns:tns="monNamespace">titi</tns:code>
      	<tns:message xmlns:tns="monNamespace">toto</tns:message>
      </tns:value>
      <tns:value xmlns:tns="monNamespace">
      	<tns:code xmlns:tns="monNamespace">tata</tns:code>
      	<tns:message xmlns:tns="monNamespace">tutu</tns:message>
      </tns:value>
      <tns:value xmlns:tns="monNamespace">
      	<tns:code xmlns:tns="monNamespace"/>
      	<tns:message xmlns:tns="monNamespace"/>
      </tns:value>
    </xsd:root>
    Vous pouvez m'aider à faire ça ?

    Merci.

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 557
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 557
    Points : 21 616
    Points
    21 616
    Par défaut
    J'ai pas compris l'exemple.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 167
    Points : 69
    Points
    69
    Par défaut
    Je veux que le script duplique le noeud fils du noeud racine (avec les elements qu'il contient).

    Dans mon exemple, le noeud racine est "root".
    Son premier noeud fils est "value" qui contient les éléments "code" et "message".

    Ce noeud à été dupliqué et rajouté à la fin du noeud racine, et les éléments ont été vidés.

    Ca se comprend, ou c'est toujours flou ?

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 557
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 557
    Points : 21 616
    Points
    21 616
    Par défaut
    Ben maintenant que tu nous as bien expliqué ce qui change entre les exemples et quel est le raisonnement qui provoque ce changement, c'est plus clair. Il faut reconnaître que l'idée de faire ça ne vient pas spontanément à l'esprit.

    Je pense que tu peux :

    - appeler un template spécial à la fin de ton template de base, pour lequel tu select="/*/*[1]"
    - Dans ce template spécial, tu fais un <copy> du nœud en cours pour avoir son nom et son namespace
    - Dans ce copy, tu fais un for-each pour lequel tu select="*"
    - Dans ce for-each, tu fais juste un <copy/> pour avoir le nom et le namespace de l'élément mais pas son contenu.

    Ça devrait faire l'affaire
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 167
    Points : 69
    Points
    69
    Par défaut
    Merci pour ces instructions.
    J'ai essayé de les suivre. Voilà ce que j'ai fait :
    - appeler un template spécial à la fin de ton template de base, pour lequel tu select="/*/*[1]"
    - Dans ce template spécial, tu fais un <copy> du nœud en cours pour avoir son nom et son namespace
    Soit le XSL 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
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
      <xsl:output method="xml"/>
     
    <xsl:template match="/node()">
      <xsl:copy>
        <xsl:apply-templates/>
        <xsl:call-template name="duplicate">
          <xsl:with-param name="myNode">
            <xsl:value-of select="/*/*[1]" />
          </xsl:with-param>
        </xsl:call-template>
      </xsl:copy>
    </xsl:template>
     
    <xsl:template match="node()|@*">
       <xsl:copy>
           <xsl:apply-templates select="@*"/>
           <xsl:apply-templates/>
       </xsl:copy>
    </xsl:template>
     
    <xsl:template name="duplicate">
      <xsl:param name="myNode" />
     
      <xsl:copy>
        <xsl:value-of select="myNode" />
      </xsl:copy>
    </xsl:template>
     
    </xsl:stylesheet>
    Ce qui me donne en sortie (avec en entrée le code de mon premier post) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?xml version="1.0" encoding="UTF-8"?><xsd:root xmlns:xsd="monNamespace" xmlns:xsi="http://www.w3.org/2delegatedCn001/XMLSchema-instance">
      <tns:value xmlns:tns="monNamespace">
      	<tns:code>titi</tns:code>
      	<tns:message>toto</tns:message>
      </tns:value>
      <tns:value xmlns:tns="monNamespace">
      	<tns:code>tata</tns:code>
      	<tns:message>tutu</tns:message>
      </tns:value>
    <xsd:root/></xsd:root>
    Donc déjà, il y'a un problème : le noeud récupéré est <root> alors que ça aurait dû être <tns:value>.

    Vous pouvez m'aider à avancer ?

    Merci.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 167
    Points : 69
    Points
    69
    Par défaut
    Ok, c'est bon, j'y suis arrivé en suivant tes consignes thelvin, merci.
    Voila ce que ça donne :
    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
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
      <xsl:output method="xml"/>
     
      <xsl:template match="/node()">
        <xsl:copy>
          <xsl:apply-templates/>
        </xsl:copy>
      </xsl:template>
     
      <xsl:template match="/*/*[last()]">
        <xsl:copy>
          <xsl:apply-templates/>
        </xsl:copy>
        <xsl:call-template name="duplicate" />
      </xsl:template>
     
      <xsl:template match="node()|@*">
         <xsl:copy>
             <xsl:apply-templates select="@*"/>
             <xsl:apply-templates/>
         </xsl:copy>
      </xsl:template>
     
      <xsl:template name="duplicate">
        <xsl:copy>
          <xsl:for-each select="./*">
           <xsl:copy />
          </xsl:for-each>
        </xsl:copy>
      </xsl:template>
     
    </xsl:stylesheet>
    et en sortie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?xml version="1.0" encoding="UTF-8"?><xsd:root xmlns:xsd="monNamespace" xmlns:xsi="http://www.w3.org/2delegatedCn001/XMLSchema-instance">
      <tns:value xmlns:tns="monNamespace">
      	<tns:code>titi</tns:code>
      	<tns:message>toto</tns:message>
      </tns:value>
      <tns:value xmlns:tns="monNamespace">
      	<tns:code>tata</tns:code>
      	<tns:message>tutu</tns:message>
      </tns:value><tns:value xmlns:tns="monNamespace"><tns:code/><tns:message/></tns:value>
    </xsd:root>
    Par contre ça ne marche que pour un niveau de profondeur donné.
    Si je modifie le fichier en entrée avec un niveau de profondeur supplémentaire pour le noeud premier noeud fils, ça ne fonctionne plus.

    Exemple :
    Si 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
    <xsd:root xmlns:xsd="monNamespace" xmlns:xsi="http://www.w3.org/2delegatedCn001/XMLSchema-instance" xsi:type="xsd:StrArray">
      <tns:value xmlns:tns="monNamespace">
      	<tns:code xmlns:tns="monNamespace">titi</tns:code>
      	<tns:message xmlns:tns="monNamespace">toto</tns:message>
      	<tns:description xmlns:tns="monNamespace">
    	  <tns:sujet xmlns:tns="monNamespace">pif</tns:sujet>
     	  <tns:contenu xmlns:tns="monNamespace">paf</tns:contenu>
    	</tns:description>
      </tns:value>
      <tns:value xmlns:tns="monNamespace">
      	<tns:code xmlns:tns="monNamespace">tata</tns:code>
      	<tns:message xmlns:tns="monNamespace">tutu</tns:message>
      	<tns:description xmlns:tns="monNamespace">
    	  <tns:sujet xmlns:tns="monNamespace">pof</tns:sujet>
     	  <tns:contenu xmlns:tns="monNamespace">puf</tns:contenu>
    	</tns:description>
      </tns:value>
    </xsd:root>
    Avec ma feuille XSL actuelle, ça ne va PAS me donner :
    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
    <xsd:root xmlns:xsd="monNamespace" xmlns:xsi="http://www.w3.org/2delegatedCn001/XMLSchema-instance" xsi:type="xsd:StrArray">
      <tns:value xmlns:tns="monNamespace">
      	<tns:code xmlns:tns="monNamespace">titi</tns:code>
      	<tns:message xmlns:tns="monNamespace">toto</tns:message>
      	<tns:description xmlns:tns="monNamespace">
    	  <tns:sujet xmlns:tns="monNamespace">pif</tns:sujet>
     	  <tns:contenu xmlns:tns="monNamespace">paf</tns:contenu>
    	</tns:description>
      </tns:value>
      <tns:value xmlns:tns="monNamespace">
      	<tns:code xmlns:tns="monNamespace">tata</tns:code>
      	<tns:message xmlns:tns="monNamespace">tutu</tns:message>
      	<tns:description xmlns:tns="monNamespace">
    	  <tns:sujet xmlns:tns="monNamespace">pof</tns:sujet>
     	  <tns:contenu xmlns:tns="monNamespace">puf</tns:contenu>
    	</tns:description>
      </tns:value>
      <tns:value xmlns:tns="monNamespace">
      	<tns:code xmlns:tns="monNamespace" />
      	<tns:message xmlns:tns="monNamespace" />
      	<tns:description xmlns:tns="monNamespace">
    	  <tns:sujet xmlns:tns="monNamespace" />
     	  <tns:contenu xmlns:tns="monNamespace" />
    	</tns:description>
      </tns:value>
    </xsd:root>
    -----------

    Autrement dit, il me faudrait modifier ma feuille XSL pour qu'elle soit plus générique, et qu'elle me duplique le premier noeud du schéma en entrée, quel que soit le niveau de profondeur de ce noeud.

    Je pense qu'il faudrait je modifie le template "duplicate" pour qu'il soit récursif.
    Mais je sais pas trop à quoi devrait ressembler mon algorithme après ça.

    Je sais pas si j'ai été assez clair dans mes explications ?
    Vous pouvez m'aider ?

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 167
    Points : 69
    Points
    69
    Par défaut
    Ca y est, ça marche.

    Il suffisait de rajouter un test dans le template "duplicate". Et ainsi faire en sorte qu'il se rappelle automatiquement lorsque le noeud courant contient des noeuds fils.

    Bref, si ça peut servir à quelqu'un d'autre, voila le XSL final :
    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
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
      <xsl:output method="xml"/>
     
      <xsl:template match="/node()">
        <xsl:copy>
          <xsl:apply-templates/>
        </xsl:copy>
      </xsl:template>
     
      <xsl:template match="/*/*[last()]">
        <xsl:copy>
          <xsl:apply-templates/>
        </xsl:copy>
        <xsl:call-template name="duplicate" />
      </xsl:template>
     
      <xsl:template match="node()|@*">
         <xsl:copy>
             <xsl:apply-templates select="@*"/>
             <xsl:apply-templates/>
         </xsl:copy>
      </xsl:template>
     
      <xsl:template name="duplicate">
        <xsl:copy>
          <xsl:for-each select="./*">
           <xsl:if test="count(./*) &gt; 0">
             <xsl:call-template name="duplicate" />
           </xsl:if>
           <xsl:if test="count(./*) &lt;= 0">
             <xsl:copy />
           </xsl:if>
          </xsl:for-each>
        </xsl:copy>
      </xsl:template>
     
    </xsl:stylesheet>

  8. #8
    Membre émérite
    Avatar de polymorphisme
    Homme Profil pro
    Publishing
    Inscrit en
    Octobre 2009
    Messages
    1 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Octobre 2009
    Messages : 1 460
    Points : 2 371
    Points
    2 371
    Par défaut
    Bonjour,

    je me demande à quoi pourrais servir ce genre de code !!!
    Article : Installation de Cocoon
    Je ne réponds pas aux MP à caractère technique.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    167
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 167
    Points : 69
    Points
    69
    Par défaut
    D'abord faut voir mon schéma XML comme une table de structure : chaque noeud fils du noeud racine est un objet du tableau.

    Ensuite, imagine un langage qui gère très mal (voire pas du tout) les tableaux et les fonctions qu'on peut s'attendre à avoir sur un tableau, tel que BPEL.
    Mais par contre ce langage peut appeler du XSLT.

    Tu combine les 2 et tu obtiens une gestion des tableaux dans un langage qui le gérait très mal ;-)

Discussions similaires

  1. Réponses: 1
    Dernier message: 01/06/2006, 17h18
  2. [XSL] egalité de noeud
    Par luta dans le forum XSL/XSLT/XPATH
    Réponses: 11
    Dernier message: 14/01/2006, 23h58
  3. [xml/xsl] Problème de noeuds et attributs
    Par Avallach dans le forum XSL/XSLT/XPATH
    Réponses: 5
    Dernier message: 14/01/2006, 14h31
  4. [XSL] Accès à un noeud dans une boucle
    Par Trin dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 15/11/2005, 14h32
  5. xsl ---> filtrage des noeuds avec "not"
    Par yos dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 12/07/2005, 11h26

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