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 :

XML > CSV - créer des copies pour chaque tuple [XSLT 1.0]


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Membre confirmé
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2009
    Messages
    339
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2009
    Messages : 339
    Points : 586
    Points
    586
    Par défaut XML > CSV - créer des copies pour chaque tuple
    Bonjour,

    Je dois transformer un fichier XML ayant plusieurs noeuds du même niveaux, en CSV.
    Les différents noeuds-frères sont liés entre eux par des clés multiples.

    Mon problème : je n'arrive pas à comprendre comment utiliser <xsl:copy> ou <xsl:copy-of> pour obtenir le résultat attendu : une duplication des parties pour obtenir 1 ligne par tuple.

    Mon 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
    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
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    <?xml version='1.0' encoding='ISO-8859-1'?>
    <EXPORT>
    	<PART_1>
    		<FORFAIT>
    			<NAME>
    				<![CDATA[Item n°1]]>
    			</NAME>
    			<CODE>114</CODE>
    			<PART_CODE>201</PART_CODE>
    			<ENGINE>
    				<![CDATA[A]]>
    			</ENGINE>
    			<LABOUR_CODE>231044009</LABOUR_CODE>
    		</FORFAIT>
    		<FORFAIT>
    			<NAME>
    				<![CDATA[Item n°2]]>
    			</NAME>
    			<CODE>115</CODE>
    			<PART_CODE>202</PART_CODE>
    			<ENGINE>
    				<![CDATA[B]]>
    			</ENGINE>
    			<LABOUR_CODE>4554003330</LABOUR_CODE>
    		</FORFAIT>
    		<FORFAIT>
    			<NAME>
    				<![CDATA[Item n°3]]>
    			</NAME>
    			<CODE>116</CODE>
    			<PART_CODE>203</PART_CODE>
    			<ENGINE>
    				<![CDATA[C]]>
    			</ENGINE>
    			<LABOUR_CODE>8794312220</LABOUR_CODE>
    		</FORFAIT>
    	</PART_1>
    	<PART_2>
    		<SPARE_PART>
    			<PART_CODE>201</PART_CODE>
    			<ENGINE>
    				<![CDATA[A]]>
    			</ENGINE>
    			<PART_NAME>
    				<![CDATA[Descriptif 201 A]]>
    			</PART_NAME>
    			<PART_QUANTITY>1.00</PART_QUANTITY>
    			<PART_SALE_PRICE>328.60</PART_SALE_PRICE>
    		</SPARE_PART>
    		<SPARE_PART>
    			<PART_CODE>201</PART_CODE>
    			<ENGINE>
    				<![CDATA[A]]>
    			</ENGINE>
    			<PART_NAME>
    				<![CDATA[Descriptif 201 A blabla]]>
    			</PART_NAME>
    			<PART_QUANTITY>1.00</PART_QUANTITY>
    			<PART_SALE_PRICE>66.05</PART_SALE_PRICE>
    		</SPARE_PART>
    		<SPARE_PART>
    			<PART_CODE>202</PART_CODE>
    			<ENGINE>
    				<![CDATA[A]]>
    			</ENGINE>
    			<PART_NAME>
    				<![CDATA[Descriptif 202 A]]>
    			</PART_NAME>
    			<PART_QUANTITY>1.00</PART_QUANTITY>
    			<PART_SALE_PRICE>38.10</PART_SALE_PRICE>
    		</SPARE_PART>
    		<SPARE_PART>
    			<PART_CODE>202</PART_CODE>
    			<ENGINE>
    				<![CDATA[B]]>
    			</ENGINE>
    			<PART_NAME>
    				<![CDATA[Descriptif 202 B blabla]]>
    			</PART_NAME>
    			<PART_QUANTITY>1.00</PART_QUANTITY>
    			<PART_SALE_PRICE>563.00</PART_SALE_PRICE>
    		</SPARE_PART>
    		<SPARE_PART>
    			<PART_CODE>203</PART_CODE>
    			<ENGINE>
    				<![CDATA[C]]>
    			</ENGINE>
    			<PART_NAME>
    				<![CDATA[Descriptif 203 C blabla]]>
    			</PART_NAME>
    			<PART_QUANTITY>1.00</PART_QUANTITY>
    			<PART_SALE_PRICE>4.50</PART_SALE_PRICE>
    		</SPARE_PART>
    		<SPARE_PART>
    			<PART_CODE>203</PART_CODE>
    			<ENGINE>
    				<![CDATA[C]]>
    			</ENGINE>
    			<PART_NAME>
    				<![CDATA[Descriptif 203 C nouveau texte]]>
    			</PART_NAME>
    			<PART_QUANTITY>1.00</PART_QUANTITY>
    			<PART_SALE_PRICE>4.40</PART_SALE_PRICE>
    		</SPARE_PART>
    		<SPARE_PART>
    			<PART_CODE>203</PART_CODE>
    			<ENGINE>
    				<![CDATA[C]]>
    			</ENGINE>
    			<PART_NAME>
    				<![CDATA[Descriptif 203 C dernier texte]]>
    			</PART_NAME>
    			<PART_QUANTITY>1.00</PART_QUANTITY>
    			<PART_SALE_PRICE>2.00</PART_SALE_PRICE>
    		</SPARE_PART>
    	</PART_2>
    </EXPORT>
    Le résultat attendu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    NAME;CODE;PART_CODE;ENGINE;LABOUR_CODE;PART_NAME;PART_QUANTITY;PART_SALE_PRICE
    Item n°1;114;201;A;231044009;Descriptif 201 A;1.00;328.60
    Item n°1;114;201;A;231044009;Descriptif 201 A blabla;1.00;66.05
    Item n°2;115;202;B;4554003330;Descriptif 202 B blabla;1.00;563.00
    Item n°3;116;203;C;8794312220;Descriptif 203 C blabla;1.00;4.50
    Item n°3;116;203;C;8794312220;Descriptif 203 C nouveau texte;1.00;4.40
    Item n°3;116;203;C;8794312220;Descriptif 203 C dernier texte;1.00;2.00
    Je parviens à ce résultat pour l'instant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    NAME;CODE;PART_CODE;ENGINE;LABOUR_CODE;PART_NAME;PART_QUANTITY;PART_SALE_PRICE
    Item n°1;114;201;A;231044009
    Item n°2;115;202;B;4554003330
    Item n°3;116;203;C;8794312220
    Avec ce XSLT :
    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
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    	xmlns:csv="csv:csv">
     
     
    	<xsl:variable name="delimiter" select="'&quot;;&quot;'"/>
    	<xsl:variable name="startline" select="'&quot;'"/>
    	<xsl:variable name="endline" select="'&quot;'"/>
     
     
    	<csv:columns>
    		<!-- PART_1 -->
    		<column>NAME</column>
    		<column>CODE</column>
    		<column>PART_CODE</column>
    		<column>ENGINE</column>
    		<column>LABOUR_CODE</column>
    		<!-- PART_2 -->
    		<column>PART_NAME</column>
    		<column>PART_QUANTITY</column>
    		<column>PART_SALE_PRICE</column>
    	</csv:columns>
     
    	<xsl:template match="/">
    		<!-- Output the CSV header -->
    		<xsl:for-each select="document('')/*/csv:columns/*">
    			<xsl:value-of select="."/>
    			<xsl:if test="position() != last()">
    				<xsl:value-of select="$delimiter"/>
    			</xsl:if>
    		</xsl:for-each>
    		<xsl:text>
    		</xsl:text>
    		<!-- Output rows for each matched property -->
    		<xsl:apply-templates select="//FORFAIT" />
    	</xsl:template>
     
    	<xsl:template match="FORFAIT">
    		<xsl:copy>
     
    			<xsl:value-of select="$startline" />
     
    			<xsl:variable name="current_op_part_code" select ="$forfait/*[name()='OPERATION_PART_CODE']" />
     
    			<!-- NAME -->
    			<xsl:value-of select="NAME" />
    			<xsl:value-of select="$delimiter"/>
     
    			<!-- CODE -->
    			<xsl:value-of select="CODE" />
    			<xsl:value-of select="$delimiter"/>
     
    			<!-- PART_CODE -->
    			<xsl:value-of select="PART_CODE" />
    			<xsl:value-of select="$delimiter"/>
     
    			<!-- ENGINE -->
    			<xsl:value-of select="ENGINE" />
    			<xsl:value-of select="$delimiter"/>
     
    			<!-- LABOUR_CODE -->
    			<xsl:value-of select="LABOUR_CODE" />
    			<xsl:value-of select="$delimiter"/>
     
     
    		</xsl:copy>
     
    		<xsl:value-of select="$endline" />
     
    		<xsl:text>
    		</xsl:text>
    	</xsl:template>
    Précisions :
    - Il faut partir de <Part_1> et boucler sur <part_2> pour obtenir autant de <PART_CODE> et <ENGINE> qui correspondent...
    - Je sais que le XSL peut être factorisé mais pour l'instant j'avance à tâtons...
    - J'ai largement édulcoré le fichier en entrée et le résultat obtenu ... pour ne vous exposer que le problème rencontré

    Merci pour votre aide !

  2. #2
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par Isythiel Voir le message
    - Il faut partir de <Part_1> et boucler sur <part_2> pour obtenir autant de <PART_CODE> et <ENGINE> qui correspondent...
    Vraiment ? Hummm... Tu pourrais préciser pourquoi c'est ça qu'il faut faire ?

    Parce que ce que je vois, moi, c'est que tu cherches à obtenir autant de lignes qu'il y a de <SPARE_PART> dans <PART_2>.
    Du coup, là, il faudrait simplement boucler sur tous les <SPARE_PART> et générer une ligne pour chacun. Reste à aller à chaque fois chercher les infos qui t'intéressent et se trouvent ailleurs.


    À part, ça, quelques conseils :
    - Ce que tu veux générer n'est pas du XML, donc les copies ne seront pas utiles, et sont même à éviter sur les éléments.
    - Tu cherches à générer du CSV, inconnu de XSLT, mais qui peut être considéré comme du pur texte. Il faudrait donc indiquer que tu génères du texte avec <xsl:output method="text"/>.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre confirmé
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2009
    Messages
    339
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2009
    Messages : 339
    Points : 586
    Points
    586
    Par défaut
    D'accord donc j'explicite un peu...

    Mon fichier contient en réalité 7 <part_x>, et c'est un modèle en étoile dont le centre est <part_1>.

    donc pour 1 <part_1>, j'ai par exemple : 2 <part_2>, 5 <part_3>, 3 <part_4>....
    Toutes les <part_x> sont liées à <part_1> par un code ou un id...

    Ce qui doit me donner dans ce cas... 30 lignes, soit 1 pour chaque tuple.

    Nous sommes d'accord que sur le plan logique, c'est une hérésie. Mais c'est la demande de mon client, et je ne suis pas chef de projet sur ce projet, donc pas de communication possible : je fais du code et-puis-c'est-tout

  4. #4
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Ok cette fois j'ai compris.

    Mais donc, du coup, tu veux simplement faire des boucles imbriquées, non ?

    C'est-à-dire dans ton template <xsl:template match="FORFAIT"> tu pourrais faire :

    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
    <xsl:variable name="forfait" select="current()"/>
    <xsl:for-each select="//PART_2/SPARE_PART">
      <xsl:variable name="spare" select="current()"/>
      <xsl:for-each select="//PART_3/bidule">
        <xsl:variable name="bidule" select="current()"/>
        <!-- et ainsi de suite -->
                <xsl:for-each select="//PART_27/truc">
                  <xsl:variable name="truc" select="current()"/>
     
                  <!-- et dans la boucle la plus profonde, on fait ce qu'on a à faire -->
                  <xsl:value-of select="concat(
                     $forfait/NAME, $delim, $forfait/CODE, $delim, ...
                     $spare/PART_CODE, $delim, $spare/ENGINE, $delim, ...
                     ...
                     )"/>
                </xsl:for-each>
      </xsl:for-each>
    </xsl:for-each>
    Un truc comme ça, ça irait ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre confirmé
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2009
    Messages
    339
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2009
    Messages : 339
    Points : 586
    Points
    586
    Par défaut
    Yes !!

    Nickel, merci beaucoup pour ton aide...
    Je commençais à approcher de la solution dans mon coin
    Et j'en suis aussi arrivée à la conclusion qu'il n'était pas nécessaire d'utiliser des "copy" comme on me l'a suggéré plus tôt.

    Merci pour le temps accordé à mon problème !

    Bonne soirée

  6. #6
    Membre confirmé
    Femme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2009
    Messages
    339
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2009
    Messages : 339
    Points : 586
    Points
    586
    Par défaut
    Bonjour,

    Un ajout très intéressant à ce post.
    Mon traitement durait 1h40 pour un fichier de 130 Mo.
    Un collègue a réussi à réduire le temps de traitement à 30 secondes en utilisant des variables temporaires et dictionnaires.

    Exemple :

    Déclaration de la variable temporaire au début du traitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:key name="dicoPart2" match="//EXPORT/PART_2/SPARE_PART" use="concat(PART_CODE, '|', ENGINE)" />
    Et dans le traitement, appel à la variable : (dans mon cas, je dois boucler sur chaque occurrence trouvée)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <xsl:variable name="part2" select="key('dicoPart2', concat($current_op_part_code, $concatSeparator, $current_engine))"/>
    	<xsl:for-each select="$part2" >
                     <!--     affichage des variables    -->
            </xsl:for-each>

    En espérant que ça puisse servir à d'autres

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

Discussions similaires

  1. Créer des JTexField pour chaque colonne de mon Jtable
    Par virus321 dans le forum Composants
    Réponses: 2
    Dernier message: 29/11/2013, 01h43
  2. Comment créer des variables pour chaque ligne d'une table
    Par Slyvore dans le forum Développement de jobs
    Réponses: 4
    Dernier message: 24/04/2012, 14h24
  3. Réponses: 4
    Dernier message: 21/03/2008, 17h40
  4. [Sessions] Comment creer des sessions pour chaque visiteur
    Par developower dans le forum Langage
    Réponses: 2
    Dernier message: 06/10/2005, 12h55
  5. Réponses: 2
    Dernier message: 04/08/2005, 19h00

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