2

<type>2 つの類似した xml ファイルをマージする必要がありますが、次の例のように、共通のタグで一致するレコードのみをマージする必要があります。

file1.xml は

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

file2.xml は

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

の出力があるように

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

xslでこれを行う基本は何ですか? どうもありがとう。

4

3 に答える 3

5

このスタイルシート:

<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>

この入力で (整形式):

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

出力:

<root>
    <node>
        <type>a</type>
        <name>jill</name>
        <name>joe</name>
    </node>
    <node>
        <type>b</type>
        <name>sam</name>
    </node>
</root>
于 2010-12-09T19:26:42.383 に答える
1

他の初心者に役立つ場合に備えて、これを行っている間に学んだ情報を追加する価値があると思いました。テスト コード名を変更して、xsl で使用されている用語と混同しないようにしました。それが最善の方法なのか、最も効率的な方法なのかはわかりませんが、うまくいきます (いくつか注意点があります!)。

「情報」ノードを保持したかったのですが、元のコードではそれが失われました。別の一致テンプレートをコーディングすると、それが出力に保持されます。また、私がコーディングした方法では、このノードは入力ファイル (x1) にある場合にのみ保持されます。(x2) ファイルにある場合は、保持されません。これは、私が繰り返しを書いた方法である必要があります。理想的には、どちらの入力ファイルからも保持したいのですが、まだその方法を考え出していません。また、ファイル名 x2 をハード コードするのではなく、msxsl を介してパラメーターとして渡すオプションが必要です。確かにこれを行う方法があるに違いありませんが、まだ追跡できていません。

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>

したがって、msx​​ls コマンドを使用すると、次のようになります。

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

以下のデータで次の結果が得られます。

ファイル 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>

ファイル 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>
于 2010-12-12T11:42:15.603 に答える
0

1 つの方法は、2 番目の xml をパラメーターとして渡すことです。

2 つ目の簡単な方法は、両方の xml を 1 つのルート要素の下に連結して、

<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>

そして、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>
于 2010-12-09T19:32:47.193 に答える