根据条件合并两个xml文件

时间:2016-06-09 09:24:08

标签: xml xslt xpath

我遇到的情况似乎超出了我在XSLT中的技能。问题如下:我有两个输入文件tuplelist.xml和orderlist.xml。前者包含一些应该添加到第二个文件的信息(我在其上运行我的.xsl文件)。 文件如下所示:

编辑:文件现在包含应添加距离的实际样本。 在添加下面答案中建议的更改后,输出基本上包含了我的orderlist.xml的复制品,但没有添加距离元素。

tuplelist.xml

<TU:tuplelist xmlns:TU="www.tuplelist.com">
    <tuple xmlns="http://ws.apache.org/ns/synapse">
        <start>Regensburg, Germany</Start>
        <destination>Bremerhaven, Germany</destination>
        <distance>736 km</distance>
    </tuple>
    <!-- more <tuple> Elements here -->
</tuplelist>

orderlist.xml

<orderlist xmlns="http://ws.apache.org/ns/synapse">
    <order>
        <nr>Transportauftrag</nr>
        <sender>
            <name>somename</name>
            <street>somestreet</street>
            <number>somenumber</number>
            <zip>somezip</zip>
            <town>Regensburg</town>
            <country>Germany</country>
        </sender>
        <recipient>
            <name>aname</name>
            <street>astreet</street>
            <number>anumber</number>
            <zip>azip</zip>
            <town>Bremerhaven</town>
            <country>Germany</country>
        </recipient>
    </order>
    <!-- more <order> elements here -->
</orderlist>

现在我要做的是为每个添加拟合元素。我想要做的是将每个发送者/城镇和每个发送者/城镇与每个接收者/城镇进行比较,正如我在当前的xslt中可以看到的那样:

merge.xlst

<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:OL="http://ws.apache.org/ns/synapse"  xmlns:TL="www.tuplelist.com" xmlns:T="http://ws.apache.org/ns/synapse">

<xsl:variable name="TL" select="document('C:/Users/admin/Desktop/tuplelist.xml')" />

<xsl:template match="OL:orderlist">
    <orderlist>
        <xsl:for-each select="./OL:order">
            <xsl:copy>
                <xsl:apply-templates/>
            </xsl:copy>

            <xsl:variable name="sta" select="./OL:sender/OL:town/text()"/>
            <xsl:variable name="dest" select="./OL:recipient/OL:town/text()"/>

            <xsl:for-each select="document($TL)/TL:tuplelist/T:tuple">
                <xsl:if test="starts-with(./OL:start, sta)">
                    <xsl:if test="starts-with(./OL:destination, dest)">
                        <distance>
                            <xsl:apply-templates select="./T:distance/text()"/>
                        </distance>
                    </xsl:if>
                </xsl:if>
            </xsl:for-each>
        </xsl:for-each>
    </orderlist>
    </xsl:template>
</xsl:stylesheet>

我认为我的命名空间是正确的,似乎无法找到我做错的事情,请你帮忙解决一下? 注意:我在WSO2 ESB中运行它并且实际上看不到我的xslt的输出,因为它只打印出错误。

1 个答案:

答案 0 :(得分:1)

我想你只想要

        <xsl:variable name="sta" select="OL:sender/OL:town"/>
        <xsl:variable name="dest" select="OL:recipient/OL:town"/>

        <xsl:copy-of select="$TL/TL:tuplelist/T:tuple[starts-with(OL:start, $sta) and starts-with(OL:destination, $dest)]/T:distance">

而不是

        <xsl:variable name="sta" select="./OL:sender/OL:town/text()"/>
        <xsl:variable name="dest" select="./OL:recipient/OL:town/text()"/>

        <xsl:for-each select="document($TL)/TL:tuplelist/T:tuple">
            <xsl:if test="starts-with(./OL:start, sta)">
                <xsl:if test="starts-with(./OL:destination, dest)">
                    <distance>
                        <xsl:apply-templates select="./T:distance/text()"/>
                    </distance>
                </xsl:if>
            </xsl:if>
        </xsl:for-each>

使用<xsl:variable name="TL" select="document('file:///C:/Users/admin/Desktop/tuplelist.xml')" />代替<xsl:variable name="TL" select="document('C:/Users/admin/Desktop/tuplelist.xml')" />可能更安全甚至是必要的。

此外,如果您想使用

        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>

然后你需要添加一个模板,确保子节点处理<xsl:apply-templates/>进程,通常的方法是包含身份转换模板

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

在样式表中。

作为替代方案,您只需复制子节点即可。

        <xsl:copy>
            <xsl:copy-of select="node()"/>
        </xsl:copy>

你可能想把代码找到匹配的距离在xsl:copy之内,而不是在它之下。

最后,输入XML具有名称空间xmlns:TU="www.tuplelist.com",而您的XSLT声明xmlns:TL="www.tupelliste.com",您需要确保具有相同的网址xmlns:TL="www.tuplelist.com"

所有这些更正我已到达

<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:OL="http://ws.apache.org/ns/synapse"  xmlns:TL="www.tuplelist.com" xmlns:T="http://ws.apache.org/ns/synapse">

    <xsl:param name="tl-url" select="'test2016060901.xml'"/>
    <xsl:variable name="TL" select="document($tl-url)" />

    <xsl:template match="OL:orderlist">
        <orderlist>
            <xsl:for-each select="OL:order">
                <xsl:copy>
                    <xsl:copy-of select="node()"/>
                    <xsl:variable name="sta" select="OL:sender/OL:town"/>
                    <xsl:variable name="dest" select="OL:recipient/OL:town"/>

                    <xsl:copy-of select="$TL/TL:tuplelist/T:tuple[starts-with(OL:start, $sta) and starts-with(OL:destination, $dest)]/T:distance"/>
                </xsl:copy>

            </xsl:for-each>
        </orderlist>
    </xsl:template>
</xsl:stylesheet>

转换

<TU:tuplelist xmlns:TU="www.tuplelist.com">
    <tuple xmlns="http://ws.apache.org/ns/synapse">
        <start>New York, Country</start>
        <destination>Phoenix, SomeCountry</destination>
        <distance>190 km</distance>
    </tuple>
    <!-- more <tuple> Elements here -->
</TU:tuplelist>

<orderlist xmlns="http://ws.apache.org/ns/synapse">
    <order>
        <nr>Transportauftrag</nr>
        <sender>
            <name>somename</name>
            <street>somestreet</street>
            <number>somenumber</number>
            <zip>somezip</zip>
            <town>New York</town>
            <country>somecountry</country>
        </sender>
        <recipient>
            <name>aname</name>
            <street>astreet</street>
            <number>anumber</number>
            <zip>azip</zip>
            <town>Phoenix</town>
            <country>acountry</country>
        </recipient>
    </order>
    <!-- more <order> elements here -->
</orderlist>

进入

<orderlist xmlns:OL="http://ws.apache.org/ns/synapse" xmlns:TL="www.tuplelist.com" xmlns:T="http://ws.apache.org/ns/synapse"><order xmlns="http://ws.apache.org/ns/synapse">
        <nr>Transportauftrag</nr>
        <sender>
            <name>somename</name>
            <street>somestreet</street>
            <number>somenumber</number>
            <zip>somezip</zip>
            <town>New York</town>
            <country>somecountry</country>
        </sender>
        <recipient>
            <name>aname</name>
            <street>astreet</street>
            <number>anumber</number>
            <zip>azip</zip>
            <town>Phoenix</town>
            <country>acountry</country>
        </recipient>
    <distance xmlns:TU="www.tuplelist.com">190 km</distance></order></orderlist>

我想你想通过

来清理一些命名空间
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:OL="http://ws.apache.org/ns/synapse" xmlns:TL="www.tuplelist.com"
    exclude-result-prefixes="TL">

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

    <xsl:param name="tl-url" select="'test2016060901.xml'"/>
    <xsl:variable name="TL" select="document($tl-url)"/>

    <xsl:template match="OL:orderlist">
        <xsl:copy>
            <xsl:for-each select="OL:order">
                <xsl:copy>
                    <xsl:copy-of select="node()"/>
                    <xsl:variable name="sta" select="OL:sender/OL:town"/>
                    <xsl:variable name="dest" select="OL:recipient/OL:town"/>

                    <xsl:copy-of
                        select="$TL/TL:tuplelist/OL:tuple[starts-with(OL:start, $sta) and starts-with(OL:destination, $dest)]/OL:distance"
                    />
                </xsl:copy>

            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

但找到了匹配。