XSLT-检查for-each循环中两个节点是否相等

时间:2018-09-25 15:15:17

标签: xml xslt

这是我的XML:

<Shipment>
<AddressData>   
    <Sender>
        <PartnerID>123</PartnerID>
        <Name1>Test</Name1>         
    </Sender>
    <Receiver>
        <PartnerID>124</PartnerID>
        <Name1>Test 2</Name1>       
    </Receiver>
</AddressData>
<Packaging>
    <Package>
        <ID>1</ID>
        <Length>20</Length>
        <Width>20</Width>           
        <PackageType>Carton</PackageType>
    </Package>
    <Package>
        <ID>2</ID>
        <Length>20</Length>
        <Width>20</Width>           
        <PackageType>Carton</PackageType>
    </Package>
</Packaging>
<Items>
    <Item>
        <PackageID>1</PackageID>
        <Partnumber>1234</Partnumber>
        <Quantity>3</Quantity>
    </Item>
    <Item>
        <PackageID>1</PackageID>
        <Partnumber>1235</Partnumber>
        <Quantity>3</Quantity>
    </Item>
    <Item>
        <PackageID>1</PackageID>
        <Partnumber>1236</Partnumber>
        <Quantity>3</Quantity>
    </Item>
    <Item>
        <PackageID>2</PackageID>
        <Partnumber>1232</Partnumber>
        <Quantity>3</Quantity>
    </Item>
    <Item>
        <PackageID>2</PackageID>
        <Partnumber>12322</Partnumber>
        <Quantity>3</Quantity>
    </Item>
</Items>

我要完成的工作是直接在Packaging XML字段中列出每个包装的相关项目。

这样我将成为以下结果:

<Shipment>
<AddressData>
    <Sender>
        <PartnerID>123</PartnerID>
        <Name1>Test</Name1>         
    </Sender>
    <Receiver>
        <PartnerID>124</PartnerID>
        <Name1>Test 2</Name1>       
    </Receiver>
</AddressData>
<Packaging>
    <Package>
        <ID>1</ID>
        <Length>20</Length>
        <Width>20</Width>           
        <PackageType>Carton</PackageType>
        <Items>
            <Item>
                <PackageID>1</PackageID>
                <Partnumber>1234</Partnumber>
                <Quantity>3</Quantity>
            </Item>
            <Item>
                <PackageID>1</PackageID>
                <Partnumber>1235</Partnumber>
                <Quantity>3</Quantity>
            </Item>
            <Item>
                <PackageID>1</PackageID>
                <Partnumber>1236</Partnumber>
                <Quantity>3</Quantity>
            </Item>
        </Items>
    </Package>
    <Package>
        <ID>2</ID>
        <Length>20</Length>
        <Width>20</Width>           
        <PackageType>Carton</PackageType>
        <Items>
            <Item>
                <PackageID>2</PackageID>
                <Partnumber>1232</Partnumber>
                <Quantity>3</Quantity>
            </Item>
            <Item>
                <PackageID>2</PackageID>
                <Partnumber>12322</Partnumber>
                <Quantity>3</Quantity>
            </Item>
        </Items>
    </Package>
</Packaging>

</Shipment>

我尝试做的是以下XSLT转换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="Items">
</xsl:template>

<xsl:template match="Packaging">
    <Packaging>
        <xsl:for-each select="Package">
            <ID>
                <xsl:value-of select="ID"/>
            </ID>
            <Length>
                <xsl:value-of select="Length"/>
            </Length>
            <Width>
                <xsl:value-of select="Width"/>
            </Width>
            <PackageType>
                <xsl:value-of select="PackageType"/>
            </PackageType>
            <Items>
                <xsl:for-each select="../../Items/Item">
                    <xsl:if test="PackageID = ../../Packaging/Package/ID">
                    <Item>
                        <PackageID><xsl:value-of select="PackageID"/></PackageID>
                        <Partnumber><xsl:value-of select="Partnumber"/></Partnumber>
                        <Quantity><xsl:value-of select="Quantity"/></Quantity>
                    </Item>
                    </xsl:if>
                </xsl:for-each>
            </Items>
        </xsl:for-each>
    </Packaging>
</xsl:template>
</xsl:stylesheet>

我当前的XSLT转换不起作用,因为将显示所有项目,无论ID如何。 因此,if语句似乎无法正常工作。

谢谢

1 个答案:

答案 0 :(得分:2)

问题在于,for一经执行,您就处于不同的上下文中,并且先前(“程序包”中的)上下文实际上被“遗忘了”。

您可以做的是在选择商品之前将当前包裹ID存储在变量中,然后在compate中使用

xsl:for-each select="../../Items/Item"

实际上,您可以将条件放在<Items> <xsl:variable name="packageId" select="ID" /> <xsl:for-each select="../../Items/Item"> <xsl:if test="PackageID = $packageId"> <Item> <PackageID><xsl:value-of select="PackageID"/></PackageID> <Partnumber><xsl:value-of select="Partnumber"/></Partnumber> <Quantity><xsl:value-of select="Quantity"/></Quantity> </Item> </xsl:if> </xsl:for-each> </Items> 的选择中,而不是xsl:for-each

xsl:if

在这种情况下,此条件可以使用<xsl:variable name="packageId" select="ID" /> <xsl:for-each select="../../Items/Item[PackageID = $packageId]">

引用当前包节点。
current()

但是话虽如此,在这里使用<xsl:for-each select="../../Items/Item[PackageID = current()/ID]"> 可能会更好。像这样定义一个键(作为xsl:key的子键)

xsl:stylesheet

然后,您可以执行此操作...

<xsl:key name="items" match="Item" use="PackageID" />

实际上,您甚至根本不需要<xsl:for-each select="key('items', ID)"> 。使用xsl:for-each并利用身份模板。

尝试使用简化的XSLT:

xsl:apply-templates