首页 > 解决方案 > XSLT 合并两个 XML 文件

问题描述

我需要使用 XSLT 合并两个 XML 文件。转换发生在包含要合并的 XML 文件列表的 XML 文件上。

列表.xml

<?xml version="1.0" encoding="UTF-8" ?>
<files>
    <file>..\src\main\resources\testOne.xml</file>
    <file>..\src\main\resources\testTwo.xml</file>
</files>

这是我要合并的两个模板:

<xsl:template name="merge_nodes">
    <xsl:param name="fnNewDeept"/>
    <xsl:param name="snNewDeept"/>

    <xsl:for-each select="$fnNewDeept">
        <xsl:call-template name="merge_node">
            <xsl:with-param name="first-node" select="$fnNewDeept"/>
            <xsl:with-param name="second-node" select="$snNewDeept"/>
        </xsl:call-template>
    </xsl:for-each>
</xsl:template>

<xsl:template name="merge_node">
    <xsl:param name="first-node" />
    <xsl:param name="second-node" />

    <xsl:element name="{name(current())}">
        <xsl:for-each select="$second-node/@*">
            <xsl:copy/>
        </xsl:for-each>
        <xsl:if test="$first-node = '' and not(boolean($first-node/*) and boolean($second-node/*))">
            <xsl:value-of select="$second-node"/>
        </xsl:if>

        <xsl:for-each select="$first-node/@*">
            <xsl:copy/>
        </xsl:for-each>
        <xsl:if test="not(boolean($first-node/*) and boolean($second-node/*))">
            <xsl:value-of select="$first-node"/>
        </xsl:if>

        <xsl:choose>
            <xsl:when test="boolean($first-node/*) or boolean($second-node/*)">     
                <xsl:choose>                                                        
                    <xsl:when test="boolean($first-node/*/*)">                      
                        <xsl:call-template name="merge_nodes">                      
                            <xsl:with-param name="fnNewDeept" select="$first-node/*"/>
                            <xsl:with-param name="snNewDeept" select="$second-node/*"/>
                        </xsl:call-template>
                    </xsl:when>
                    <xsl:otherwise>
                        2. Value: <xsl:value-of select="current()/*"/>
                        2. Current: <xsl:value-of select="name(current()/*)"/>
                        2. First: <xsl:value-of select="name($first-node/*)"/>
                        2. Second: <xsl:value-of select="name($second-node/*)"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:otherwise>
                1. Value: <xsl:value-of select="current()"/>
                1. Current: <xsl:value-of select="name(current())"/>
                1. First: <xsl:value-of select="name($first-node)"/>
                1. Second: <xsl:value-of select="name($second-node)"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:element>
</xsl:template>

和我的两个 XML:

<?xml version="1.0" encoding="UTF-8" ?>
<first x="1">
    <second param="wt" second="true">
        <third>abc</third>
        <third>def</third>
    </second>
    <fourth>
        <fifth x="1">hij</fifth>
        <fifth>klm</fifth>
    </fourth>
    <sixth>qrs</sixth>
</first>

2.

<?xml version="1.0" encoding="UTF-8" ?>
<first y="2">
    <second param="123" second="false">
        <third>asd</third>
        <third>def</third>
    </second>
    <fourth>
        <fifth y="2">tuv</fifth>
        <fifth>wxy</fifth>
    </fourth>
    <sixth>678</sixth>
    <sixth>910</sixth>
</first>

我希望第一个文件是首选文件,以便将第二个文件合并到第一个文件中。不应出现重复元素。

预期输出:

<?xml version="1.0" encoding="UTF-8" ?>
<first x="1" y="2">
    <second param="wt" second="true">
        <third>abc</third>
        <third>def</third>
        <third>asd</third>
    </second>
    <fourth>
        <fifth x="1">hij</fifth>
        <fifth>klm</fifth>
        <fifth y="2">tuv</fifth>
        <fifth>wxy</fifth>
    </fourth>
    <sixth>qrs</sixth>
    <sixth>678</sixth>
    <sixth>910</sixth>
</first>

我得到的输出:

<?xml version="1.0" encoding="windows-1252"?><first y="2" x="1">
<second param="wt" second="true">
                            2. Value: abc
                            2. Current: third
                            2. First: third
                            2. Second: third</second>
<fourth param="wt" second="true">
                            2. Value: hij
                            2. Current: fifth
                            2. First: third
                            2. Second: third</fourth>
<sixth param="wt" second="true">
                            2. Value: 
                            2. Current: 
                            2. First: third
                            2. Second: third</sixth>
</first>

我不知道如何同时沿着两棵树运行,所以我可以复制元素。有人有什么想法吗?我只能使用 Apaches XALAN。我使用最新的 2.7.2 版本。

编辑:由于已经存在误解。转换必须适用于类似的 XML 文件,这是大问题。

标签: xmlapachexsltmergexalan

解决方案


<xsl:output method="xml" indent="yes"/>
    <xsl:variable name="doc" select="doc('merge2.xml')"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="first">
        <xsl:copy>
        <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="$doc/first/@*"/>
            <xsl:apply-templates/>

        </xsl:copy>
    </xsl:template>
    <xsl:template match="second">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
            <xsl:copy-of select="$doc/first/second/third[ not(.= current()/third)]"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="fourth">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
            <xsl:copy-of select="$doc/first/fourth/fifth[ not(.= current()/fifth)]"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="sixth">
        <xsl:copy>

            <xsl:apply-templates/>

        </xsl:copy>
        <xsl:copy-of select="$doc/first/sixth[ not(.= current()/sixth)]"/>
    </xsl:template>
CHeck it

推荐阅读