使用两个标准的XSLT 1.0组值

时间:2015-10-27 20:33:50

标签: xml xslt xslt-1.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>

1 个答案:

答案 0 :(得分:0)

这部分是一个分组问题,在XSLT 1.0中,您可以使用名为Muenchian Grouping的技术

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

<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>