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 :

Changer l'ordre des noeuds enfants [XSLT 1.0]


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 160
    Points : 89
    Points
    89
    Par défaut Changer l'ordre des noeuds enfants
    Bonjour à tous,

    Je patauge un peu sur ce problème depuis un moment maintenant sans parvenir à trouver la solution. La transformation XSLT sert à changer le format d'un fichier XML vers un XML légèrement différent. Je décrirai d'abord brièvement les formats d'entrée et de sortie, puis vous donnerai le code XSL que j'utilise. Enfin, je décrirai le problème auquel je me heurte.

    Format d'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
    22
    23
    24
    25
    26
    27
     
    <IX_PH>
    	<PH>
    		<CDL>
    		(...)
    		</CDL>
    		<WH>
    			<WL>
    			(...)
    			</WL>
    			<WEL>
    			(...)
    			</WEL>
    			<PNRF>
    				<PN (...) />
    				<PN (...) />
    				(...)
    			</PNRF>
    		</WH>
    		<GH>
    		(...)
    		</GH>
    		<R>
    		(...)
    		</R>
    	</PH>
    </IX_PH>
    En sortie, il faut :
    - renommer IX_PH en IX_WH
    - renommer PH en WH
    - renommer les nœuds PN en EF et le nœud PNRF en EFRF
    - "ramener" les nœuds WL, WEL et PNRF un niveau au-dessus
    - mettre le nœud PNRF à la fin (après le nœud R)

    Ça donne le format de sortie 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
     
    <IX_WH>
    	<WH>
    		<CDL>
    		(...)
    		</CDL>
    		<WL>
    		(...)
    		</WL>
    		<WEL>
    		(...)
    		</WEL>
    		<GH>
    		(...)
    		</GH>
    		<R>
    		(...)
    		</R>
    		<EFRF>
    			<EF (...) />
    			<EF (...) />
    			(...)
    		</EFRF>
    	</PH>
    </IX_WH>
    Le code XSL utilisé est le suivant (avec les modifs proposées ci-dessous) :
    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
    80
    81
    82
    83
    84
    85
    86
    87
     
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     
    	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
     
    	<xsl:template match="IX_PH">
    		<xsl:element name="IX_WH">
    			<xsl:copy-of select="@*"/>
    			<xsl:apply-templates/>
    		</xsl:element>
    	</xsl:template>
     
    	<xsl:template match="PH">
    		<WH>
    			<xsl:copy-of select="@*[not(name()='Version')]"/>
    			<xsl:attribute name="VersionNb"><xsl:value-of select="@Version"/></xsl:attribute> <!-- Renommage d'un attribut -->
    			<xsl:apply-templates/>
    			<xsl:apply-templates select="WH/PNRF"/>
    		</WH>
    	</xsl:template>
     
     	<xsl:template match="WH">
     		<xsl:apply-templates select="*[not(self::PNRF)]"/>
      	</xsl:template>
     
    	<xsl:template match="CDL">
    		<xsl:element name="CDL">
    			<xsl:copy-of select="@*"/>
    			<xsl:apply-templates/>
    		</xsl:element>
    	</xsl:template>
     
    	<!-- Renommer les nœuds CDL/CD/CA en CDL/CD/A -->
    	<xsl:template match="CD">
    		<xsl:element name="CD">
    			<xsl:copy-of select="@* | node()[name()='P'][name()='S'][name()='Version'][name()='UA']"/>
    			<xsl:for-each select="./CA">
    				<xsl:element name="A">
    					<xsl:copy-of select="@*"/>
    				</xsl:element>
    			</xsl:for-each>
    			<xsl:copy-of select="node()[not(name()='P')][not(name()='S')][not(name()='Version')][not(name()='UA')][not(name()='CA')]"/>
    			<xsl:apply-templates/>
    		</xsl:element>
    	</xsl:template>
     
    	<xsl:template match="WL">
    		<xsl:element name="WL">
    			<xsl:copy-of select="*"/>
    			<xsl:apply-templates/>
    		</xsl:element>
    	</xsl:template>
     
    	<xsl:template match="WEL">
    		<xsl:element name="WEL">
    			<xsl:copy-of select="*"/>
    			<xsl:apply-templates/>
    		</xsl:element>
    	</xsl:template>
     
    	<xsl:template match="GH">
    		<xsl:element name="GH">
    			<xsl:copy-of select="*"/>
    			<xsl:apply-templates/>
    		</xsl:element>
    	</xsl:template>
     
    	<xsl:template match="R">
    		<xsl:element name="R">
    			<xsl:copy-of select="*"/>
    			<xsl:apply-templates/>
    		</xsl:element>
    	</xsl:template>
     
    	<xsl:template match="PNRF">
    		<xsl:element name="EFRF">
    			<xsl:for-each select="./PN">
    				<xsl:element name="EF">
    					<xsl:copy-of select="@*"/>
    					<xsl:apply-templates/>
    				</xsl:element>
    			</xsl:for-each>
    		</xsl:element>
    	</xsl:template>
     
    </xsl:stylesheet>
    Mon problème est qu'en output, le nœud EFRF se situe entre les nœuds WEL et GH au lieu de se trouver à la fin. Voilà.

    Désolé si mon post est compliqué, brouillon, pas clair ou autre, mais j'ai réellement besoin d'aide sur cette affaire Je peux tout à fait faire un post explicatif simplifié si nécessaire.

    Merci d'avance pour vos lumières !

  2. #2
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    C'est dans ton template PH (noeud qui contient les fils que tu veux réordonner) qu'il faut que tu dises dans quel ordre tu veux lire ces noeuds :
    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
    	<xsl:template match="PH">
    		<xsl:element name="WH">
    			<xsl:copy-of select="@*[not(name()='Version')]"/>
    			<xsl:attribute name="VersionNb"><xsl:value-of select="@Version"/></xsl:attribute> <!-- Renommage d'un attribut -->
    			<xsl:for-each select="CDL">
    				<xsl:apply-templates select="."/>
    			</xsl:for-each>
    			<xsl:for-each select="WL">
    				<xsl:apply-templates select="."/>
    			</xsl:for-each>
    			<!-- ... -->
    			<xsl:for-each select="PNRF">
    				<xsl:apply-templates select="."/>
    			</xsl:for-each>
    		</xsl:element>
    	</xsl:template>

  3. #3
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 559
    Points : 21 621
    Points
    21 621
    Par défaut
    Citation Envoyé par hobotalker Voir le message
    Désolé si mon post est compliqué, brouillon, pas clair ou autre, mais j'ai réellement besoin d'aide sur cette affaire Je peux tout à fait faire un post explicatif simplifié si nécessaire.
    Honnêtement, il me semble pile-poil comme il faut, ton post. C'est la bonne manière de présenter les choses, et il est à peu près aussi simple et court que la description du problème le permet.
    Ne change rien, fais toujours comme ça, et tu rendras heureux les gens d'ici ('fin bon, on t'en voudra pas si tu progresses au point de te débrouiller, hein ).


    La réponse de Loceka me semble correcte, je te propose une alternative : tu appliques les templates sur tous les enfants de <WH> sauf celui que tu veux déplacer. Celui-là, tu l'appelles séparément dans le niveau au-dessus.

    À peu près comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <xsl:template match="PH">
      <WH>
        <xsl:apply-templates/>
        <xsl:apply-templates select="WH/PNRF"/>
      </WH>
    </xsl:template>
     
    <xsl:template match="WH">
      <xsl:apply-templates select="*[not(PNRF)]"/>
    </xsl:template>

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 160
    Points : 89
    Points
    89
    Par défaut
    Bonjour, et merci pour vos réponses.

    J'ai essayé a solution de Loceka mais cette dernière donnait des résultats plutôt exotiques ! De nombreux noeuds enfants avaient disparu.

    La deuxième proposition de solution, celle de thelvin, donne un résultat strictement identique que mon code initial.

    Toutefois, je n'avais pas précisé un détail du code XSL qui peut avoir son importance !
    Je m'en excuse d'ailleurs, mais je comprends tellement peu ce que je fais que j'ai volontairement occulté cette partie en me disant qu'elle était forcément "ignorable" (non, ce n'est pas français ).

    Le fichier d'entrée comprend un nœud source IX_PH qui doit être renommé en IX_WH en sortie. Voilà, vous savez quasiment tout. J'ai également occulté des modifications que je fais dans les enfants noeuds (de CDL, notamment). Pour le coup, je ne pense vraiment pas que cela influe sur le résultat final, mais je vais inclure la totalité de mon code XSL pour que vous ayez bien toutes les données en main. J'édite tout ça dans le post initial.

    Merci d'avance pour votre aide, encore une fois.

  5. #5
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 559
    Points : 21 621
    Points
    21 621
    Par défaut
    Citation Envoyé par hobotalker Voir le message
    La deuxième proposition de solution, celle de thelvin, donne un résultat strictement identique que mon code initial.
    Pas avec l'exemple que tu nous as donné, non. Par ailleurs le raisonnement que j'ai exposé n'a pas de faille.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 160
    Points : 89
    Points
    89
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Pas avec l'exemple que tu nous as donné, non. Par ailleurs le raisonnement que j'ai exposé n'a pas de faille.
    Je n'en doute pas, mais j'avais omis un détail sur les formats de fichier. C'est maintenant édité.

  7. #7
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Citation Envoyé par hobotalker Voir le message
    J'ai essayé a solution de Loceka mais cette dernière donnait des résultats plutôt exotiques ! De nombreux noeuds enfants avaient disparu.
    Effectivement, si tu l'as repris tel quel sans chercher à comprendre, il ne reprend que les noeuds enfants CDL, WL et PNRF.

    J'ai volontairement et explicitement (<!-- ... --> signifie que c'est à toi de compléter le code) occulté une partie du traitement qui était inutile car exactement pareil que ce que j'avais déjà écrit mais pour les autres fils.

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 160
    Points : 89
    Points
    89
    Par défaut
    Citation Envoyé par Loceka Voir le message
    Effectivement, si tu l'as repris tel quel sans chercher à comprendre, il ne reprend que les noeuds enfants CDL, WL et PNRF.

    J'ai volontairement et explicitement (<!-- ... --> signifie que c'est à toi de compléter le code) occulté une partie du traitement qui était inutile car exactement pareil que ce que j'avais déjà écrit mais pour les autres fils.
    Bien que je ne sois pas expert en XSLT, j'avais bien remplacé par tout ce qu'il faut, et cela ne fonctionnait pas.

    Encore une fois, j'avais omis un détail des formats d'entrée/sortie, cela est maintenant édité. J'ai aussi édité le code XSL que j'utilise, qui a été modifié selon les remarques de thelvin. Le problème reste identique.

    Peut-être que le fait de faire la transformation XSL par C# pose un problème, mais j'en doute fort.

  9. #9
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 559
    Points : 21 621
    Points
    21 621
    Par défaut
    Argh. Mon raisonnement était bon, mais pas le code qui l'implémente -_-°.

    C'est

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <xsl:template match="WH">
      <xsl:apply-templates select="*[not(self::PNRF)]"/>
    </xsl:template>
    Stupide erreur de copier/coller.

    Pour info c'est presque équivalent à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <xsl:template match="WH">
      <xsl:apply-templates select="*[name() != 'PNRF']"/>
    </xsl:template>

    Note : le changement de nom de l'élément racine n'a aucune incidence sur le reste.

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 160
    Points : 89
    Points
    89
    Par défaut
    thelvin,

    Une nouvelle fois merci pour ta réponse rapide. J'ai une nouvelle fois édité le code de mon post initial par ta dernière mise au point. Malheureusement, après test, les nœuds enfants de WH sortent toujours dans l'ordre suivant : CDL, WL, WEL, EFRF, GH, R (et non EFRF en dernier).

    Le C# peut-il être en cause?
    J'aurais aimé pouvoir faire la transformation via un autre moyen pour essayer d'isoler la source d'erreur (C# ou XSL) mais mon éditeur XML (XMLSpy) refuse de la faire (output vide). Existe-t-il un moyen simple et incontestable de faire cette transformation?

    Merci encore pour votre aide. Je ne remets aucunement en cause vos compétences, mais le fichier d'output est ce qu'il est, malheureusement pour moi

  11. #11
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Peux-tu nous montrer ton code XSLT actuel en entier ?
    Ce que t'as proposé thelvin me semble correct.

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 160
    Points : 89
    Points
    89
    Par défaut
    Le code XSL du post initial est désormais strictement identique à celui que j'utilise (aux noms de balises près, mais j'ai déjà vérifié 100 fois ne pas avoir fait de bêtises de ce côté-là).

  13. #13
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Je ne vois aucune raison qui ferait que ça ne marche pas, hormis une implémentation étrange du XSLT (et ça j'en ai déjà vues malheureusement...).

    Essaye avec <xsl:apply-templates select="*[name() != 'PNRF']"/> et si ça ne marche toujours pas réessaye le self:: et le name() avec node() à la place de '*'.

    J'ai déjà vu des implémentations de XSLT dont le traitement différait entre node() et * dans des contextes qui ne le justifiaient pas.

  14. #14
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 559
    Points : 21 621
    Points
    21 621
    Par défaut
    Sans doute une histoire de namespaces.

    Le code donné dans le premier post, fonctionne parfaitement sur le fichier XML donné en exemple.
    Mais l'exemple n'indique aucun namespace. Dans le vrai fichier, il est possible que les balises <PNRF> soient dans un namespace, auquel cas il faut le gérer pour les exclure et les inclure.

    Il faudrait ne pas enlever les namespaces de ton exemple, laisser tout ce qui commence par xmlns.

  15. #15
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 160
    Points : 89
    Points
    89
    Par défaut
    Merci Loceka,

    Toutefois, le problème se situait au niveau du C#. La solution proposée avec le self fonctionne désormais très bien !

    Pour finir, je vais essayer de comprendre ! Il y a quelque chose que je ne saisis pas dans le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <xsl:template match="PH">
      <WH>
        <xsl:apply-templates/>
        <xsl:apply-templates select="WH/PNRF"/>
      </WH>
    </xsl:template>
    Pourquoi le premier apply-templates ne s'applique-t-il pas à tous les nœuds enfants de PH et ne prend pas, comme "par magie", WH?
    Effectivement, on écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <xsl:template match="WH">
      <xsl:apply-templates select="*[not(self::PNRF)]"/>
    </xsl:template>
    mais le "*" ne comprend-il pas le nœud WH lui-même?

    Et comment ce premier apply-templates exclut-il PNRF? Car ce dernier est mentionné dans le second? J'aurais été tenté de faire <xsl:apply-templates select="*[not(WH/PNRF)]"/>, mais peut-être que c'est redondant !

    Dans tous les cas, un grand merci et un excellent week-end à vous deux !

  16. #16
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Quand tu es dans un élément (donc dans un template matchant un élément), tu te trouve déjà dans l'élément.
    Tout XPath relatif est donc appliqué à partir de l'élément courant et donc "*" signifie "tous les élément fils".

    Là ton traitement est le suivant
    1. Dans l'élément PH, tu demandes d'appliquer les templates à tous ses éléments fils (dont PNRF ne fait pas partie).
      • WH étant un fils de PH, tu appliques le template sur WH qui ne fait rien hormis l'application des templates sur les fils de WH à l'exception de PNRF.
    2. Dans l'élément PH, tu appliques les templates à tous les éléments WH/PNRF.


    Par contre ce serait sympa de donner la solution que tu as apporté au C# pour le cas où quelqu'un aurait le même problème que toi.

  17. #17
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 160
    Points : 89
    Points
    89
    Par défaut
    Bonjour Loceka,

    Merci pour ces explications, c'est désormais plus clair. Le problème C# est en fait une immense bêtise de ma part : pour résumer, j'avais oublié qu'en mode débug, ma méthode de transformation XSL était suivie d'une sauvegarde écrasant le résultat...

    Par contre, je mets toutefois le code permettant la transformation, ça peut effectivement être utile. Merci de noter qu'utilisant le Framework 1.1, certaines méthodes peuvent être obsolètes dans une autre version du Framework.
    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
    private void TransformXml(string strXmlFileNameInput, string strXslFileName, string strXmlFileNameOutput)
    {
    	XmlTextWriter objWriter = null;
     
    	try
    	{
    		// Create the Transformer object
    		XslTransform objTransformer = new XslTransform();
    		objTransformer.Load(strXslFileName);
     
    		// Create the Writer object
    		objWriter = new XmlTextWriter(strXmlFileNameOutput, System.Text.Encoding.UTF8);
    		objWriter.Formatting = Formatting.Indented;
     
    		// Create the destination XML XPathDoc object
    		XPathDocument objXPathDocument = new XPathDocument(strXmlFileNameInput);
     
    		// Actually transform the XML file
    		objTransformer.Transform(objXPathDocument, null, objWriter, null);
    	}
    	finally
    	{
    		if (objWriter != null)
    			objWriter.Close();
    	}
    }
    Il reste toutefois un dernier souci dans la transformation. Apparemment, les nœuds enfants des nœuds CD sont mal recopiés. Pour rappel, il faut garder l'ordre initial des nœuds enfants et simplement renommer les nœuds CA en A.

    Actuellement, le code permettant telle opération est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!-- Renommer les nœuds CA en A -->
    	<xsl:template match="CD">
    		<xsl:element name="CD">
    			<xsl:copy-of select="@* | node()[name()='P'][name()='S'][name()='Version'][name()='UA']"/>
    			<xsl:for-each select="./CA">
    				<xsl:element name="A">
    					<xsl:copy-of select="@*"/>
    				</xsl:element>
    			</xsl:for-each>
    			<xsl:copy-of select="node()[not(name()='P')][not(name()='S')][not(name()='Version')][not(name()='UA')][not(name()='CA')]"/>
    			<xsl:apply-templates/>
    		</xsl:element>
    	</xsl:template>
    De mes yeux de profane, tout me parait ici correct :
    - Le premier copy-of permet de copier les nœuds précédant les nœuds CA
    - On renomme ensuite les nœuds CA en A
    - Enfin, on copie les nœuds venant après les nœuds CA

    Dans les faits, les nœuds P ne sont pas recopiés. Des nœuds Po, non mentionnées mais englobés dans le dernier copy-of sont, eux, copiés correctement. Les nœuds CA sont également renommés convenablement.

    Encore une fois merci.

  18. #18
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 559
    Points : 21 621
    Points
    21 621
    Par défaut
    Parce que l'expression

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    node()[name()='P'][name()='S'][name()='Version'][name()='UA']
    ne sélectionne rien du tout. Elle impose quatre conditions différentes au nœud, et demande en gros qu'il ait quatre noms différents.
    Un nœud peut avoir zéro ou un nom, mais jamais quatre. Aucun nœud ne répond à ces critères.

    Tu pensais sans doute à :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *[name()='P' or name()='S' or ...]
    Qu'il serait plus logique d'écrire :


    Note : pareil pour la fin, ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    node()[not(name()='P')][not(name()='S')][not(name()='Version')][not(name()='UA')][not(name()='CA')]
    Serait un peu plus simple ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    node()[not(self::P or self::S or ...)]

  19. #19
    Expert confirmé
    Avatar de Loceka
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 2 276
    Points : 4 845
    Points
    4 845
    Par défaut
    Citation Envoyé par hobotalker Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:copy-of select="@* | node()[name()='P'][name()='S'][name()='Version'][name()='UA']"/>
    Ici tu sélectionnes :
    • tous les attributs
    • tous les noeuds dont le nom est 'P' et dont le nom est 'S' et...


    Ce qui revient à dire rien en ce qui concerne les noeuds.
    Ce que tu voulais écrire c'était :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:copy-of select="@* | *[name()='P' or name()='S' or name()='Version' or name()='UA']"/>
    Edit :
    Comme l'a dit thelvin, le mieux est en fait de passer par l'élément lui-même et non par son nom :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:copy-of select="@* | P | S | Version | UA"/>
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:copy-of select="*[not(self::P or self::S or self::Version or self::UA]"/>
    Il est aussi préférable d'utiliser "*" plutôt que "node()" car * ne match que les noeuds de type élément (c'est ce que tu veux) tandis que node() match tous les noeuds (éléments, attributs, commentaires, ...).

  20. #20
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    160
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 160
    Points : 89
    Points
    89
    Par défaut
    D'accord. Je paraphrase mais ça signifie donc que les différentes conditions entre crochets sont implicitement reliées par un ET LOGIQUE, au lieu d'un OU LOGIQUE comme je l'imaginais.

    Je vais utiliser la même méthode pour les deux copy-of, aucun raison particulière de passer une première fois par le "name()" et une seconde par le "self".

    Je vais donc faire quelque chose du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <xsl:template match="CD">
    		<xsl:element name="CD">
    			<xsl:copy-of select="@* | node()[self::P or self::S or self::Version or self::UA]"/>
    			<xsl:for-each select="./CA">
    				<xsl:element name="A">
    					<xsl:copy-of select="@*"/>
    				</xsl:element>
    			</xsl:for-each>
    			<xsl:copy-of select="node()[not(self::P or self::S or self::Version or self::UA or self::CA)]"/>
    			<xsl:apply-templates/>
    		</xsl:element>
    	</xsl:template>
    Et effectivement cela fonctionne Merci pour cette rectification !

    Excellentes fêtes de Pâques à vous deux.

    Cordialement,
    hobotalker

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

Discussions similaires

  1. [Thunderbird] changer l'ordre des comptes
    Par Eusebius dans le forum Thunderbird
    Réponses: 2
    Dernier message: 26/07/2006, 09h08
  2. [C#-XML] Récupérer les valeurs des noeuds enfants
    Par cyllix dans le forum Windows Forms
    Réponses: 1
    Dernier message: 23/06/2006, 11h54
  3. Rajout colonne - changer l'ordre des colonnes ?
    Par Coptere dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 13/09/2005, 10h56
  4. changer l'ordre des dates dans table
    Par lordyan dans le forum Requêtes
    Réponses: 11
    Dernier message: 14/01/2005, 11h12
  5. [XML] Parser selon des noeuds enfants
    Par GLDavid dans le forum Modules
    Réponses: 5
    Dernier message: 20/08/2004, 20h42

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