Question

Je dois fusionner deux fichiers xml similaires, mais uniquement les enregistrements qui correspondent à des balises communes, e.g.<type> dans l'exemple suivant:

file1.xml est

<node>
    <type>a</type>
    <name>joe</name>
</node>
<node>
    <type>b</type>
    <name>sam</name>
</node>

file2.xml est

<node>
    <type>a</type>
    <name>jill</name>
</node>

pour que j'ai une sortie de

<node>
    <type>a</type>
    <name>jill</name>
    <name>joe</name>
</node>
<node>
    <type>b</type>
    <name>sam</name>
</node>

Quelles sont les bases de le faire, en xsl? Merci beaucoup.

Était-ce utile?

La solution

Cette feuille de style:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kElementByType" match="*[not(self::type)]" use="../type"/>
    <xsl:param name="pSource2" select="'file2.xml'"/>
    <xsl:variable name="vSource2" select="document($pSource2,/)"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="type">
        <xsl:variable name="vCurrent" select="."/>
        <xsl:call-template name="identity"/>
        <xsl:for-each select="$vSource2">
            <xsl:apply-templates select="key('kElementByType',$vCurrent)"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Avec cette entrée (wellformed):

<root>
    <node>
        <type>a</type>
        <name>joe</name>
    </node>
    <node>
        <type>b</type>
        <name>sam</name>
    </node>
</root>

Sortie:

<root>
    <node>
        <type>a</type>
        <name>jill</name>
        <name>joe</name>
    </node>
    <node>
        <type>b</type>
        <name>sam</name>
    </node>
</root>

Autres conseils

Je pensais que ce la peine d'ajouter quelques informations supplémentaires, je l'ai appris en faisant cela, dans le cas où il est utile à tout autre débutants. J'ai changé mes noms de code de test afin qu'ils ne sont pas potentiellement confondus avec certains des termes utilisés dans le xsl. Je ne sais pas si c'est la façon meilleure ou la plus efficace de faire les choses, mais il fonctionne (avec quelques mises en garde!).

Je voulais garder le noeud « info » et le code original perdu. Le codage d'un modèle de correspondance séparé conserve dans la sortie. De plus, la façon dont je codé il, ce noeud ne sont conservées que si elle est dans le fichier d'entrée (x1). Si elle est dans le fichier (x2), il ne soit pas maintenu. Ce doit être la façon dont je l'ai écrit les itérations. Idéalement, je voudrais garder de l'un des fichiers d'entrée, mais ne l'ai pas travaillé sur la façon de le faire encore. De plus, je voudrais avoir la possibilité de passer le x2 nom de fichier comme paramètre, via msxsl, plutôt que d'avoir du mal codé. Il doit sûrement y avoir un moyen de le faire, mais je n'ai pas réussi à le suivre vers le bas encore.

fichier xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kElementByType" match="*[not(self::keynode)]" use="../keynode"/>
    <xsl:param name="pSource2" select="'x2.xml'"/>
    <xsl:variable name="vSource2" select="document($pSource2,/)"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="info">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="keynode">
        <xsl:variable name="vCurrent" select="."/>
        <xsl:call-template name="identity"/>
        <xsl:for-each select="$vSource2">
            <xsl:apply-templates select="key('kElementByType',$vCurrent)"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Ainsi, en utilisant la commande msxls:

msxsl.exe x1.xml test.xsl -o out.xml

donne les résultats suivants avec les données ci-dessous:

fichier x1.xml:

<root>
    <info>
        <id>147</id>
    </info>
    <nodetype>
        <keynode>annajon</keynode>
        <note>
        <source>source1</source>
        <name>Anna Jones</name>
        </note>
    </nodetype>
    <nodetype>
        <keynode>brucejon</keynode>
        <note>
        <source>source1</source>
        <name>Bruce Jones</name>
        </note>
    </nodetype>
</root>

fichier x2.xml:

<root>
    <nodetype>
        <keynode>annajon</keynode>
        <note>
        <source>source2</source>
        <name>Anna Jones</name>
        </note>
    </nodetype>
    <nodetype>
        <keynode>iangore</keynode>
        <note>
        <source>source2</source>
        <name>Ian Gore</name>
        </note>
    </nodetype>
</root>

out.xml:

<?xml version="1.0" encoding="UTF-16"?><root>
    <info>
        <id>147</id>
    </info>
    <nodetype>
        <keynode>annajon</keynode><note>
        <source>source2</source>
        <name>Anna Jones</name>
        </note>
        <note>
        <source>source1</source>
        <name>Anna Jones</name>
        </note>
    </nodetype>
    <nodetype>
        <keynode>brucejon</keynode>
        <note>
        <source>source1</source>
        <name>Bruce Jones</name>
        </note>
    </nodetype>
</root>

Une façon consiste à passer deuxième xml en tant que paramètre,

Deuxième façon plus facile est de concaténer les deux xmls sous un même élément racine à

<root>
    <node>
        <type>a</type>
        <name>joe</name>
    </node>
    <node>
        <type>b</type>
        <name>sam</name>
    </node>
    <node>
        <type>a</type>
        <name>jill</name>
    </node>
</root>

et ne fusionnez à l'aide de 2

<xsl:template match="/root">
    <xsl:for-each select="node">
        <xsl:variable name="type" select="type"/>
        <node> 
           <type><xsl:value-of select="$type"/></type>
           <xsl:for-each select="../node[type=$type]">
              <name><xsl:value-of select"name"/></name>
           </xsl:for-each>
       </node>
    </xsl:for-each>
</xsl:template>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top