Bonjour,

Je souhaite transformer un fichier XML en un autre fichier XML. J'ai lu le tutorial sur XSLT mais j'avoue que je ne m'en sort pas trop...

Mon fichier source à cette forme :
<root>
<voiture>
<marque>Renault</marque>
<modele>Clio</modele>
</voiture>
<voiture>
<marque>Renault</marque>
<modele>R25</modele>
</voiture>
</root>

Je souhaite faire des regroupements pour qu'il devienne :
<root>
<voiture>
<marque>renault</marque>
<modele>Clio</modele>
<modele>R25</modele>
</voiture>
</root>

Merci de votre aide,
Je suis preneur d'un exemple,

Laurent
Modifié par laurent35 (26 Oct 2005 - 19:17)
Administrateur
Bonjour et bienvenue sur ce Forum,

merci de baliser les 2 parties XML par [ code] XML... [ /code] en éditant le message, comme cela est indiqué dans les Règles


La doc XSLT 2.0 du W3C a beaucoup plus d'exemples que la 1.0, de mémoire. http://www.w3.org/TR/xslt20/

Une approche possible est d'utiliser l'exemple de l'Identity Transformation et de le modifier par un "if" pour faire <xsl:apply-templates> ou <xsl:call-template> mais ce n'est pas la seule, tout dépend ce que fait/doit faire le reste de ta transformation ??

Felipe
Une solution en passant

Le code xml
<root>
    <voiture>
        <marque>Renault</marque>
        <modele>Clio</modele>
    </voiture>
    <voiture>
        <marque>Ford</marque>
        <modele>Mondeo</modele>
    </voiture>
    <voiture>
        <marque>Renault</marque>
        <modele>R25</modele>
    </voiture>    
    <voiture>
        <marque>Ford</marque>
        <modele>Focus</modele>
    </voiture>
</root>


Le code xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output indent="yes"/>
    <xsl:template match="/">
        <root>
            <xsl:apply-templates select="//voiture"/>
        </root>
    </xsl:template>
    <xsl:template match="voiture">
        <xsl:apply-templates select="marque[not(preceding::marque=.)]"/>
    </xsl:template>
    <xsl:template match="marque">
        <xsl:variable name="marque">
            <xsl:value-of select="."/>
        </xsl:variable>
        <voiture>
            <marque>
                <xsl:value-of select="$marque"/>
            </marque>
            <xsl:apply-templates select="//modele">
                <xsl:with-param name="marque" select="$marque"/>
            </xsl:apply-templates>
        </voiture>
    </xsl:template>
    <xsl:template match="modele">
        <xsl:param name="marque"/>
        <xsl:if test="../marque = $marque">
            <modele>
                <xsl:value-of select="."/>
            </modele>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>


Le résultat

<?xml version="1.0" encoding="utf-8"?>
<root>
   <voiture>
      <marque>Renault</marque>
      <modele>Clio</modele>
      <modele>R25</modele>
   </voiture>
   <voiture>
      <marque>Ford</marque>
      <modele>Mondeo</modele>
      <modele>Focus</modele>
   </voiture>
</root>


note : la balise code ne semble pas maintenir l'indentation du document
Modifié par h2o (23 Oct 2005 - 20:08)
Dans le problème posé, l'utilisation d'une clef offre la possibilité d'obtenir une transformation élégante et concise :
<?xml version='1.0' encoding='ISO-8859-1'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="voiture" match="voiture" use="./marque"/>
<xsl:template match="/" >
<xsl:for-each select="//marque[not(preceding::marque=.)]">
 <voiture>
<xsl:copy-of select="."/>
<xsl:copy-of select="key('voiture',.)/modele"/>
</voiture>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Très élégant, effectivement.

Je vais utiliser plus souvent l'élément key dans certains de mes regroupements.
J'ai entre autre un agenda où j'ai a regrouper des événements par date et où une clé s'appliquera parfaitement.

Merci.
Administrateur
laurent35 a écrit :
Merci pour l'ensemble de vos réponses... très claires.
Laurent

Bravo Smiley smile

Considères-tu le sujet comme [Résolu] ?