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 :

Tri fichier xml [XSLT 1.0]


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Nouveau Candidat au Club
    Inscrit en
    Août 2010
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 5
    Points : 1
    Points
    1
    Par défaut Tri fichier xml
    Bonjour ,

    j'aimerai trier ce fichier xml et ordonnancer les différentes balises "<ordreMouvement>" selon le numéro <idEntete> (par ordre croissant).

    Voici le fichier xml 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
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <msgL3-1 xmlns="asd2km">
    	<dateMouvement>2010-07-06</dateMouvement>
    	<codeMouvement>555</codeMouvement>
    	
    	<ordreMouvement>
    		<typeSource>Nouveau</typeSource>
    		<idEntete>80000045</idEntete>
    		<idPoste>1</idPoste>
    		<quantite>2</quantite>
    	</ordreMouvement>
    	
    	<ordreMouvement>
    		<typeSource>Nouveau</typeSource>
    		<idEntete>80000047</idEntete>
    		<idPoste>3</idPoste>
    		<quantite>2</quantite>
    	</ordreMouvement>
    	
    		<ordreMouvement>
    		<typeSource>Nouveau</typeSource>
    		<idEntete>80000046</idEntete>
    		<idPoste>2</idPoste>
    		<quantite>4</quantite>
    	</ordreMouvement>
    </msgL3-1>
    Voilà ce que j'aimerai obtenir obtenir en sortie de la transformation xsl :

    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
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <msgL3-1 xmlns="asd2km">
    	<dateMouvement>2010-07-06</dateMouvement>
    	<codeMouvement>555</codeMouvement>
    	
    	<ordreMouvement>
    		<typeSource>Nouveau</typeSource>
    		<idEntete>80000045</idEntete>
    		<idPoste>1</idPoste>
    		<quantite>2</quantite>
    	</ordreMouvement>
    	
    	<ordreMouvement>
    		<typeSource>Nouveau</typeSource>
    		<idEntete>80000046</idEntete>
    		<idPoste>2</idPoste>
    		<quantite>4</quantite>
    	</ordreMouvement>
    	
    	<ordreMouvement>
    		<typeSource>Nouveau</typeSource>
    		<idEntete>80000047</idEntete>
    		<idPoste>3</idPoste>
    		<quantite>2</quantite>
    	</ordreMouvement>
    
    </msgL3-1>
    J'ai créé pour cela cette feuille xsl :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <xsl:stylesheet version="1.0" xmlns: xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="xml" encoding="ISO-8859-1"/>
     
    <xsl:template match="/">
        <ordreMouvement>
          <xsl:for-each select="ordreMouvement">
            <xsl:sort select="idEntete" data-type="number" order="ascending"/>
          </xsl:for-each>
        </ordreMouvement>
    </xsl:template>
     
    </xsl:stylesheet>
    En testant la transformation xsl avec xml spy, je n'obtiens pas le xml en sortie trié.

    Pouvez vous m'aider ?

    Merci

  2. #2
    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
    Il ne manque pas grand-chose.

    - Le plus important : tu fais un for-each, que tu tries... Et tu ne fais rien à l'intérieur -_-°. À quoi sert-il dans ce cas ?
    Ce que tu veux faire est probablement un <xsl:copy-of/>, pour copier le nœud en cours et ses descendants.

    - Important : ton document source contient xmlns="asd2km" à la racine. Tu dois donc aussi le mettre à la racine de ta feuille XSLT.
    Malheureusement, c'est un namespace par défaut, et on ne peut pas utiliser de namespace par défaut dans les expressions xPath.
    Il faut donc en plus ajouter un namespace préfixé genre xmlns:asd="asd2km" (tu peux mettre ce que tu veux qui ne soit pas déjà pris à la place de asd.)
    Puis, l'utiliser dans tes expressions xPath :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <xsl:for-each select="asd:ordreMouvement">
      <xsl:sort select="asd:idEntete" data-type="number" order="ascending"/>
      <xsl:copy-of/>
    </xsl:for-each>
    Il faut en plus ajouter, à la racine de la XSLT, l'attribut exclude-result-prefixes="asd", pour qu'il ne te transfère pas le xmlns:asd="asd2km" dans ton document destination.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns="asd2km"
      xmlns:asd="asd2km"
      exclude-result-prefixes="asd"
    >

    - <ordreMouvement> ne doit pas être en dehors du for-each, parce qu'alors il n'y en a qu'un seul, qui entoure tout le contenu de ta boucle. De toute façon, copy-of se chargera de l'insérer.

    - Tu as oublié le nœud racine, <msgL3-1>, ainsi que ses deux enfants <dateMouvement> et <codeMouvement> au début.

    - Le xmlns:fo ne sert à rien si tu n'en as pas besoin.

  3. #3
    Nouveau Candidat au Club
    Inscrit en
    Août 2010
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Bonjour thelvin,

    merci beaucoup pour ta réponse rapide. Effectivement il manquait le copy of

    J'ai corrigé ma feuille xsl avec tes recommandations :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns: xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
      xmlns="asd2km"
      xmlns:asd="asd2km"
      exclude-result-prefixes="asd">
    	<xsl:output method="xml" indent="no" encoding="ISO-8859-1"/>
    	<xsl:template match="/asd:msgL3-1">
    		<xsl:for-each select="asd:ordreMouvement">
    			<xsl:sort select="asd:idEntete"/>
    			<xsl:copy-of select="."/>
    		</xsl:for-each>
    	</xsl:template>
    </xsl:stylesheet>
    En lancant un test avec xmlspy, j'obtiens bien les ordres de mouvements triés mais je ne récupère pas les balises en dessous ou au dessus des ordres mouvements du fichier xml initial (<dateMouvement>2010-07-06</dateMouvement> <codeMouvement>555</codeMouvement>). Connaitrai tu la syntaxe pour récupérer les autres balises non concernés par le tri ?

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 466
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 466
    Points : 1 610
    Points
    1 610
    Par défaut
    Hello,
    Avant le "for-each" tu peux ajouter des :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    <xsl:copy-of select="asd:dateMouvement"/>
    <xsl:copy-of select="asd:codeMouvement"/>
    ou encore :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:copy-of select="asd:dateMouvement | asd:codeMouvement"/>
    ou encore :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:copy-of select="asd:*[local-name()!='ordreMouvement']"/>

  5. #5
    Nouveau Candidat au Club
    Inscrit en
    Août 2010
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    merci Morbo.

    En fait, le fichier xml à modifier peut avoir d'autres balises avant et après les ordres de mouvement. C'est pour cela que j'aimerai récupérer tel quel toutes ces balises ainsi que les ordres de mouvements triés.

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 466
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 466
    Points : 1 610
    Points
    1 610
    Par défaut
    La dernière proposition devrait couvrir ce besoin.

  7. #7
    Nouveau Candidat au Club
    Inscrit en
    Août 2010
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    Oui j'ai rajouté cette syntaxe et cela me récupère bien les dernières balises.

    Voici le dernier xsl :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns: xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
      xmlns="asd2km"
      xmlns:asd="asd2km"
      exclude-result-prefixes="asd">
    	<xsl:output method="xml" indent="no" encoding="ISO-8859-1"/>
    	<xsl:template match="/asd:msgL3-1">
    	<xsl:copy-of select="asd:*[local-name()!='ordreMouvement']"/>
    		<xsl:for-each select="asd:ordreMouvement">
    			<xsl:sort select="asd:idEntete"/>
    			<xsl:copy-of select="."/>
    		</xsl:for-each>
    	</xsl:template>
    </xsl:stylesheet>

    J'obtiens 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
    16
    17
    18
    19
    20
    21
    22
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <dateMouvement xmlns="asd2km">2010-07-06</dateMouvement>
    <codeMouvement xmlns="asd2km">555</codeMouvement>
    <commentaire xmlns="asd2km">a</commentaire>
    <ordreMouvement xmlns="asd2km">
    	<typeSource>Nouveau</typeSource>
    	<idEntete>80000046</idEntete>
    	<idPoste>1</idPoste>
    	<quantite>2</quantite>
    </ordreMouvement>
    <ordreMouvement xmlns="asd2km">
    	<typeSource>Nouveau</typeSource>
    	<idEntete>80000047</idEntete>
    	<idPoste>1</idPoste>
    	<quantite>2</quantite>
    </ordreMouvement>
    <ordreMouvement xmlns="asd2km">
    	<typeSource>Nouveau</typeSource>
    	<idEntete>80000048</idEntete>
    	<idPoste>1</idPoste>
    	<quantite>2</quantite>
    </ordreMouvement>

    Il me manque seulement la balise principale <msgL3-1 xmlns="asd2km"> </msgL3-1>. Comment je peux la récupérer en même temps que les autres balises ?

    Es-il possible de n'ajouter le xmlns="asd2km" dans le fichier de sortie seulement dans la balise principale ?

    Merci pour vos réponses

  8. #8
    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
    Il me manque seulement la balise principale <msgL3-1 xmlns="asd2km"> </msgL3-1>. Comment je peux la récupérer en même temps que les autres balises ?
    Modifie ton template :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <xsl:template match="/asd:msgL3-1">
      <xsl:copy>
    
        [ ... Intérieur du template ... ]
    
      </xsl:copy>
    </xsl:template>

    <copy> signifie copier le nœud en cours mais pas ses enfants. Ce qu'on met à l'intérieur de <copy> sera la nouvelle descendance du nœud copié.
    À noter que <copy> copie la balise avec son nom et ses namespaces, mais ne copie pas les attributs. Ce qui n'est pas grave ici puisqu'il n'y en a pas.


    Es-il possible de n'ajouter le xmlns="asd2km" dans le fichier de sortie seulement dans la balise principale ?
    Ça va se faire tout seul, si tu as une balise ancêtre de toutes les autres.

  9. #9
    Nouveau Candidat au Club
    Inscrit en
    Août 2010
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 5
    Points : 1
    Points
    1
    Par défaut
    ca marche nickel

    merci beaucoup à tous

  10. #10
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 27
    Points : 13
    Points
    13
    Par défaut
    Bonjour,
    j'ai un problème similaire à l'exemple présenté ci-dessus.

    Néanmoins, j'ai un niveau hiérarchique de plus.
    Par exemple entre <msgL3-1> et <ordreMouvement> j'ai une balise <toto>.

    Le problème est que je n'arrive pas à gérer le tri avec cette balise.
    Alors qu'en supprimant, cette balise, tout marche nickel.

    Voici le code :
    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
    <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
    xmlns="asd2km"
    xmlns:asd="asd2km"
    exclude-result-prefixes="asd">
    <xsl:output method="xml" indent="no" encoding="ISO-8859-1"/>
    <xsl:template match="/asd:msgL3-1">
    <xsl:copy>
     
    		<xsl:copy-of select="asd:*[local-name()!='toto']"/>
    		<xsl:for-each select="asd:toto">
     
    			<xsl:copy-of select="asd:*[local-name()!='ordreMouvement']"/>
    				<xsl:for-each select="asd:ordreMouvement">
    					<xsl:sort select="asd:idEntete"/>
    					<xsl:copy-of select="."/>
    				</xsl:for-each>
    		</xsl:for-each>
    </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>
    Avec ce code je perds la balise toto dans le XML d'output.
    Merci d'avance!

  11. #11
    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
    Je comprends pas trop ta logique, mais bon, tu as oublié de copier tes balises <toto>, c'est pour ça que tu les perds. Il faut mettre un <xsl:copy>

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <xsl:for-each select="asd:toto">
      <xsl:copy>
        <!-- contenu de la balise <toto> -->
      </xsl:copy>
    </xsl:for-each>

  12. #12
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 27
    Points : 13
    Points
    13
    Par défaut
    ça marche!
    Merci

  13. #13
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 27
    Points : 13
    Points
    13
    Par défaut
    Bonjour, je suis de retour avec un nouveau problème.

    Dans mon flux XML, j'ai plusieurs balises à trier.

    J'ai donc bêtement fais ceci :
    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
    <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
    xmlns="asd2km"
    xmlns:asd="asd2km"
    exclude-result-prefixes="asd">
    <xsl:output method="xml" indent="no" encoding="ISO-8859-1"/>
    <xsl:template match="/asd:msgL3-1">
    <xsl:copy>
     
    		<xsl:copy-of select="asd:*[local-name()!='toto']"/>
    		<xsl:for-each select="asd:toto">
    			<xsl:copy>
    				<xsl:copy-of select="asd:*[local-name()!='ordreMouvement']"/>
    					<xsl:for-each select="asd:ordreMouvement">
    						<xsl:sort select="asd:idEntete"/>
    						<xsl:copy-of select="."/>
    					</xsl:for-each>
    				<xsl:copy>
    		</xsl:for-each>
    		<xsl:copy-of select="asd:*[local-name()!='titi']"/>
    		<xsl:for-each select="asd:titi">
    			<xsl:copy>
    				<xsl:copy-of select="asd:*[local-name()!='ordreBanane']"/>
    					<xsl:for-each select="asd:ordreBanane">
    						<xsl:sort select="asd:idEntete"/>
    						<xsl:copy-of select="."/>
    					</xsl:for-each>
    				<xsl:copy>
    		</xsl:for-each>
    </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>
    Mais là j'assiste à une duplication de l'ensemble des balises.
    J'ai raté un morceau?
    Ou alors il faut passer par plusieurs xsl? (une dizaine vu le nombre de balise à trier)

  14. #14
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 27
    Points : 13
    Points
    13
    Par défaut
    Je rame un peu.

    J'ai essayé plusieurs solutions.
    la plus proche du but est la suppression des balises
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:copy-of select="asd:*[local-name()!='XXXX']"/>
    Mais dans ce cas, je perds les autres balises de mon XML toutes les balises que j'ai pas besoin de trier.

    La méthode que j'ai trouvé est de recopier balise par balise même celle que je ne souhaites pas modifier.

  15. #15
    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 n'ai pas regardé ton code en détail mais je trouve qu'il y'a trop de copy un peu partout, et surtout des copy imbriqué, ce que je trouve très étrange.

    Dans la réponse de thelvin, tu remarques qu'il n'y a qu'un seul <xsl:copy>, ce qui est déjà beaucoup plus propre.

    A mon avis tes soucis viennent de là.

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

Discussions similaires

  1. [XSLT] tri d'un fichier xml
    Par Hinault Romaric dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 26/11/2009, 15h02
  2. Tri d'un fichier XML
    Par Hinault Romaric dans le forum C#
    Réponses: 4
    Dernier message: 18/11/2009, 09h49
  3. Réponses: 1
    Dernier message: 07/09/2009, 07h15
  4. Réponses: 1
    Dernier message: 20/06/2007, 10h28
  5. [XSL][débutant]trié l'ordre des éléments d'un fichier xml
    Par pistache42 dans le forum XSL/XSLT/XPATH
    Réponses: 5
    Dernier message: 19/04/2006, 10h37

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