XSLT1.0使用两个标准对值进行分组



我有这个XML:

<test>                               
   <itemGroup>        
    <item>
        <date>20151020</date>
        <time>1201</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151020</date>
        <time>1202</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151020</date>
        <time>1203</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151020</date>
        <time>1204</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151020</date>
        <time>1205</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151021</date>
        <time>1301</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151021</date>
        <time>1302</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151021</date>
        <time>1303</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151021</date>
        <time>1304</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151021</date>
        <time>1305</time>
        <amount>1.000</amount>
    </item>
</itemGroup>
<itemGroup>        
    <item>                        
        <date>20151022</date>
        <time>1047</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151022</date>
        <time>1147</time>
        <amount>1.000</amount>
    </item>                
    <item>
        <date>20151022</date>
        <time>1247</time>
        <amount>1.000</amount>
    </item>                    
</itemGroup>
<itemGroup>      
    <item>
        <date>20151020</date>
        <time>2211</time>
        <amount>1.000</amount>
    </item>
    <item>
        <date>20151020</date>
        <time>2222</time>
        <amount>1.000</amount>
    </item>                   
</itemGroup>                
</test>

以及以下XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="test">
    <Main>          
        <xsl:apply-templates select="itemGroup"/>           
    </Main>     
</xsl:template>
<xsl:template match="itemGroup">
    <xsl:comment>** item Group #<xsl:value-of select="position()"/></xsl:comment>
    <xsl:variable name="Max_Size">3</xsl:variable>
    <xsl:comment>item count : <xsl:value-of select="count(item)"/></xsl:comment>
    <xsl:comment> </xsl:comment>
    <xsl:for-each select="item[ position() mod $Max_Size = 1 or (not(date=preceding-sibling::item/date) and not(position() mod $Max_Size = 1)) ]">
        <xsl:comment>** Header <xsl:value-of select="position()"/> </xsl:comment>
        <segment name="Header">
            <xsl:attribute name="nb"><xsl:value-of select="position()"/></xsl:attribute>
            <element name="date"><xsl:value-of select="date"/></element>
            <element name="sum"><xsl:value-of select="format-number(sum(../item/amount), '0')"/></element><!--sum of all amount of this group-->                
        </segment>
        <xsl:for-each select=".|following-sibling::item[position() &lt; $Max_Size and date=preceding-sibling::item/date]">              
            <segment name="item">                   
                <element name="time"><xsl:value-of select="time"/></element>
            </segment>              
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

我得到的输出是:

<Main>
<!--** item Group #1-->
<!--item count : 10-->
<!---->
<!--** Header 1-->
<segment name="Header" nb="1">
    <element name="date">20151020</element>
    <element name="sum">10</element>
</segment>
<segment name="item">
    <element name="time">1201</element>
</segment>
<segment name="item">
    <element name="time">1202</element>
</segment>
<segment name="item">
    <element name="time">1203</element>
</segment>
<!--** Header 2-->
<segment name="Header" nb="2">
    <element name="date">20151020</element>
    <element name="sum">10</element>
</segment>
<segment name="item">
    <element name="time">1204</element>
</segment>
<segment name="item">
    <element name="time">1205</element>
</segment>
<!--** Header 3-->
<segment name="Header" nb="3">
    <element name="date">20151021</element>
    <element name="sum">10</element>
</segment>
<segment name="item">
    <element name="time">1301</element>
</segment>
<segment name="item">
    <element name="time">1302</element>
</segment>
<segment name="item">
    <element name="time">1303</element>
</segment>
<!--** Header 4-->
<segment name="Header" nb="4">
    <element name="date">20151021</element>
    <element name="sum">10</element>
</segment>
<segment name="item">
    <element name="time">1302</element>
</segment>
<segment name="item">
    <element name="time">1303</element>
</segment>
<segment name="item">
    <element name="time">1304</element>
</segment>
<!--** Header 5-->
<segment name="Header" nb="5">
    <element name="date">20151021</element>
    <element name="sum">10</element>
</segment>
<segment name="item">
    <element name="time">1305</element>
</segment>
<!--** item Group #2-->
<!--item count : 3-->
<!---->
<!--** Header 1-->
<segment name="Header" nb="1">
    <element name="date">20151022</element>
    <element name="sum">3</element>
</segment>
<segment name="item">
    <element name="time">1047</element>
</segment>
<segment name="item">
    <element name="time">1147</element>
</segment>
<segment name="item">
    <element name="time">1247</element>
</segment>
<!--** item Group #3-->
<!--item count : 2-->
<!---->
<!--** Header 1-->
<segment name="Header" nb="1">
    <element name="date">20151020</element>
    <element name="sum">2</element>
</segment>
<segment name="item">
    <element name="time">2211</element>
</segment>
<segment name="item">
    <element name="time">2222</element>
</segment>
</Main>

我想要实现的是根据这些标准对价值观进行分组。

1-同一日期的所有项目。2-组大小不得超过"Max_size"(3),应启动一个新组。

我能够分别实现这两个标准——当试图将它们结合在一起时,它就停止了工作。

可选奖金问题:只有当前组的总金额。

我必须使用1.0

以下是我期望的输出:

<Main>
<!--** item Group #1-->
<!--item count : 10-->
<!---->
<!--** Header 1-->
<segment name="Header" nb="1">
    <element name="date">20151020</element>
    <element name="sum">3</element>
</segment>
<segment name="item">
    <element name="time">1201</element>
</segment>
<segment name="item">
    <element name="time">1202</element>
</segment>
<segment name="item">
    <element name="time">1203</element>
</segment>
<!--** Header 2-->
<segment name="Header" nb="2">
    <element name="date">20151020</element>
    <element name="sum">3</element>
</segment>
<segment name="item">
    <element name="time">1204</element>
</segment>
<segment name="item">
    <element name="time">1205</element>
</segment>
<!--** Header 3-->
<segment name="Header" nb="3">
    <element name="date">20151021</element>
    <element name="sum">3</element>
</segment>
<segment name="item">
    <element name="time">1301</element>
</segment>
<segment name="item">
    <element name="time">1302</element>
</segment>
<segment name="item">
    <element name="time">1303</element>
</segment>
<!--** Header 4-->
<segment name="Header" nb="4">
    <element name="date">20151021</element>
    <element name="sum">2</element>
</segment>    
<segment name="item">
    <element name="time">1304</element>
</segment>
<segment name="item">
    <element name="time">1305</element>
</segment>    
<!--** item Group #2-->
<!--item count : 3-->
<!---->
<!--** Header 1-->
<segment name="Header" nb="1">
    <element name="date">20151022</element>
    <element name="sum">3</element>
</segment>
<segment name="item">
    <element name="time">1047</element>
</segment>
<segment name="item">
    <element name="time">1147</element>
</segment>
<segment name="item">
    <element name="time">1247</element>
</segment>
<!--** item Group #3-->
<!--item count : 2-->
<!---->
<!--** Header 1-->
<segment name="Header" nb="1">
    <element name="date">20151020</element>
    <element name="sum">2</element>
</segment>
<segment name="item">
    <element name="time">2211</element>
</segment>
<segment name="item">
    <element name="time">2222</element>
</segment>
</Main>

这在一定程度上是一个分组问题,在XSLT1.0中,您可以使用名为Muenchian grouping 的技术

在给定的itemGroup内,您正在按日期对item元素进行分组,因此您可以定义一个类似的键

<xsl:key name="items" match="item" use="concat(generate-id(..), '|', date)" />

为了获得每个日期的不同item元素,通常您会执行此

<xsl:for-each select="item[count(. | key('items', concat(generate-id(..), '|', date))[1]) = 1]">

但是,想要选择3人一组,会增加复杂性。你可以用这个可怕的表达:

<xsl:for-each 
     select="item[count(. | key('items', concat(generate-id(..), '|', date))[position() mod $Max_Size = 1]) 
                  = ceiling(count(key('items', concat(generate-id(..), '|', date))) div $Max_Size)]">

然后,组中的项目将被定义为:

<xsl:variable name="group" select=".|following-sibling::item[position() &lt; $Max_Size and date = current()/date]" />

尝试此XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="xml"/>
<xsl:key name="items" match="item" use="concat(generate-id(..), '|', date)" />
<xsl:template match="test">
    <Main>   
        <xsl:apply-templates select="itemGroup"/>           
    </Main>     
</xsl:template>
<xsl:template match="itemGroup">
    <xsl:comment>** item Group #<xsl:value-of select="position()"/></xsl:comment>
    <xsl:variable name="Max_Size">3</xsl:variable>
    <xsl:comment>item count : <xsl:value-of select="count(item)"/></xsl:comment>
    <xsl:comment> </xsl:comment>
    <xsl:for-each select="item[count(. | key('items', concat(generate-id(..), '|', date))[position() mod $Max_Size = 1]) = ceiling(count(key('items', concat(generate-id(..), '|', date))) div $Max_Size)]">
        <xsl:comment>** Header <xsl:value-of select="position()"/> </xsl:comment>
        <xsl:variable name="group" select=".|following-sibling::item[position() &lt; $Max_Size and date = current()/date]" />
        <segment name="Header">
            <xsl:attribute name="nb"><xsl:value-of select="position()"/></xsl:attribute>
            <element name="date"><xsl:value-of select="date"/></element>
            <element name="sum"><xsl:value-of select="format-number(sum($group/amount), '0')"/></element><!--sum of all amount of this group-->                
        </segment>
        <xsl:for-each select="$group">              
            <segment name="item">                   
                <element name="time"><xsl:value-of select="time"/></element>
            </segment>              
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

相关内容

  • 没有找到相关文章

最新更新