我有这个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() < $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() < $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() < $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>