XSLT通过条件连接/非条件连接合并两个XML

时间:2014-03-04 16:40:56

标签: xml xslt

我希望这很容易。我在同一个文件中有两个XML结构。

<?xml version="1.0" encoding="UTF-8"?>
<DBS>
    <DB>
        <DBNAME>DB1</DBNAME>
        <LOCAL>US</LOCAL>
    </DB>
    <DB>
        <DBNAME>DB2</DBNAME>
        <LOCAL>CN</LOCAL>
    </DB>
</DBS>
<SCRIPTS>
    <Script>
        <ID>1</ID>
        <SPTEXT>TEST1</SPTEXT>
    </Script>
    <Script>
        <ID>2</ID>
        <SPTEXT>TEST2</SPTEXT>
    </Script>
</SCRIPTS>

如何将它合并在一起。所以它会像

<?xml version="1.0" encoding="UTF-8"?>
<RUNSQS>
    <RUNSQ>
        <DBNAME>DB1</DBNAME>
        <LOCAL>US</LOCAL>
        <SCRIPT>TEST1</SCRIPT>
    </RUNSQ>
    <RUNSQ>
        <DBNAME>DB2</DBNAME>
        <LOCAL>CN</LOCAL>
        <SCRIPT>TEST1</SCRIPT>
    </RUNSQ>
    <RUNSQ>
        <DBNAME>DB1</DBNAME>
        <LOCAL>US</LOCAL>
        <SCRIPT>TEST2</SCRIPT>
    </RUNSQ>
    <RUNSQ>
        <DBNAME>DB2</DBNAME>
        <LOCAL>CN</LOCAL>
        <SCRIPT>TEST2</SCRIPT>
    </RUNSQ>
</RUNSQS>

我试图通过两个集合使用for-each paracter。但问题是当我到达每个人时。我没有用第二个foreach引用DBNAME。也无法使变量可引用。

1 个答案:

答案 0 :(得分:0)

您的转换首先不起作用,因为您的XML文件格式不正确。您必须通过以下任一方法解决这个问题:

1)将XML分成两个文件:

<强> dbs.xml

<?xml version="1.0" encoding="UTF-8"?>
<DBS>
    <DB> ... </DB>
    ...
</DBS>

<强> scripts.xml

<?xml version="1.0" encoding="UTF-8"?>
<SCRIPTS>
    <Script>...</Script>
...
</SCRIPTS>

2)添加公共根节点:

<root>
    <DBS>...</DBS>
    <SCRIPTS>...</SCRIPTS>
</root>

假设,从您的示例中,您根据相对位置Script树中选择SCRIPTS个节点(实际上这有点危险。您可以使用不同的条件(例如IDDBNAME的后缀相比)。无论如何,我假设相对位置的选择。如果您决定使用其他标准进行测试,则必须调整代码。

1)对于可以将XML放在不同文件中的情况,您可以在xsl:variablexsl:param中加载每个文件:

<xsl:param name="dbs" select="document('dbs.xml')" />
<xsl:param name="scripts" select="document('scripts.xml')" />

使用$dbs$scripts作为根,从每个文件中选择节点。此样式表使用此策略实现您的目标:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="dbs" select="document('dbs.xml')" />
    <xsl:param name="scripts" select="document('scripts.xml')" />

    <xsl:template match="/">
        <RUNSQS>           
            <xsl:apply-templates select="$dbs/DBS"/>
        </RUNSQS>
    </xsl:template>

    <xsl:template match="DB">
        <xsl:variable name="pos" select="position()" />
        <RUNSQ>
            <xsl:copy-of select="*"/>
            <xsl:apply-templates select="$scripts/SCRIPTS/Script[$pos]" />
        </RUNSQ>
    </xsl:template>

    <xsl:template match="Script">
        <SCRIPT><xsl:value-of select="SPTEXT"/></SCRIPT>
    </xsl:template>

</xsl:stylesheet>

(我使用<xsl:strip-space>来避免节点position()中的错误,因为我正在使用该标准来选择$scripts中的节点。)

如果您只需在文件中添加<root>,使其成为格式良好的XML,那么您可以从root开始匹配,然后从那里选择绝对所需的其他元素或文件中的相对XPath:

<xsl:template match="root"> <!-- change this to match root -->
    <RUNSQS>           
        <xsl:apply-templates select="DBS"/>
    </RUNSQS>
</xsl:template>

<xsl:template match="DB">
    <xsl:variable name="pos" select="position()" />
    <RUNSQ>
        <xsl:copy-of select="*"/>
        <xsl:apply-templates select="../../SCRIPTS/Script[$pos]" /> <!-- this, or absolute XPath -->
    </RUNSQ>
</xsl:template>