XSLT 1.0 使用两个标准对值进行分组
XSLT 1.0 group values using two criterias
我有这个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>
这部分是一个分组问题,在 XSLT 1.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]">
但是你想要 select 组 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>
我有这个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>
这部分是一个分组问题,在 XSLT 1.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]">
但是你想要 select 组 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>