xslt 1.0中的嵌套循环,具有唯一值

时间:2013-12-06 18:24:01

标签: xslt xslt-1.0

我有以下xml作为输入...

    <ns0:Root xmlns:ns0="http://testing">
    <DetailRecord>
        <Upc>1</Upc>
        <UnitCost>111.111</UnitCost>
    </DetailRecord>
    <DetailRecord>
        <Upc>1</Upc>
        <UnitCost>111.222</UnitCost>
    </DetailRecord>
    <DetailRecord>
        <Upc>1</Upc>
        <UnitCost>111.222</UnitCost>
    </DetailRecord>
    <DetailRecord>
        <Upc>2</Upc>
        <UnitCost>111.333</UnitCost>
    </DetailRecord>
    <DetailRecord>
        <Upc>3</Upc>
        <UnitCost>111.111</UnitCost>
    </DetailRecord>
</ns0:Root>

我正在尝试生成以下输出...

1
   111.111
   111.222
2
   111.333
3
   111.111

每个“Upc”值在输出中应该是不同的。 “Upc”下面应该是不同“UnitCost”值的列表。我尝试了多种变化而没有这样的运气。我的最新迭代如下:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="upcNum" match="//DetailRecord/Upc" use="./text()"/>
    <xsl:key name="cst" match="UnitCost" use="."/>

    <xsl:template match="/">
        <html>
            <body>
                <xsl:for-each select="//DetailRecord/Upc[generate-id(.) = generate-id(key('upcNum',.))]">
                    <xsl:sort select="."/>
                    <xsl:variable name="myUpc" select="."/> 
                    <h1>
                        <xsl:value-of select="current()" />
                    </h1>

                    <xsl:for-each select="//DetailRecord[Upc=current()]/UnitCost">
                        <div><xsl:value-of select="current()" /></div>
                    </xsl:for-each>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

这是不正确的,因为它生成“UnitCost”不明显的输出。我收到的输出如下......

1
   111.111
   111.222
   111.222
2
   111.333
3
   111.111

我怎样才能正确地实现我想要的目标?

1 个答案:

答案 0 :(得分:1)

您已将此正确识别为分组问题并使用Muenchian Grouping,这很好!但在这种情况下,您只需进行两次分组,一次只需 Upc ,然后进入每个 Upc 实例中的 UnitCost

首先,对于 Upc 的分组,您的密钥很好,但考虑将 DetailRecord 元素分组为 Upc <可能会更简单/ strong>,并像这样定义键。要点不是你不需要在这里指定 DetailRecord 的完整xpath,该键将在文档中的任何位置拾取元素(你只需要担心指定一个路径,如果你想限制选择的内容)

<xsl:key name="upcNum" match="DetailRecord" use="Upc"/>

在为每个不同的 Upc 元素分组 UnitCost 元素方面,您需要一个复合键...

<xsl:key name="cst" match="DetailRecord" use="concat(Upc, '|', UnitCost)"/>

|实际上可以是此处的任何字符,只要它不会出现在您连接的任何值中。

使用此键,要为不同的 Upc 获取不同的 UnitCost 元素,您只需执行此操作(这只是muenchian分组)。

<xsl:for-each 
     select="key('upcNum', Upc)
             [generate-id(.) = generate-id(key('cst',concat(Upc, '|', UnitCost)))]">

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="upcNum" match="DetailRecord" use="Upc"/>
    <xsl:key name="cst" match="DetailRecord" use="concat(Upc, '|', UnitCost)"/>

    <xsl:template match="/">
        <html>
            <body>
                <xsl:for-each select="//DetailRecord[generate-id(.) = generate-id(key('upcNum', Upc))]">
                    <xsl:sort select="."/>
                    <xsl:variable name="myUpc" select="."/> 
                    <h1>
                        <xsl:value-of select="Upc" />
                    </h1>

                    <xsl:for-each select="key('upcNum', Upc)[generate-id(.) = generate-id(key('cst',concat(Upc, '|', UnitCost)))]">
                        <div><xsl:value-of select="UnitCost" /></div>
                    </xsl:for-each>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>