XSLT 1.0按年份分组并添加不存在的年份

时间:2012-12-28 08:54:00

标签: xslt

我有xml如下(使用xslt 1.0 ):

<?xml version="1.0" encoding="utf-8"?>
    <receives>
    <receive>
    <Year>2013</Year>
    <money>120</money>
    </receive>
    <receive>
    <Year>2013</Year>
    <money>150</money>
    </receive>
    <receive>
    <Year>2014</Year>
    <money>130</money>
    </receive>
    <receive>
    <Year>2011</Year>
    <money>120</money>
        </receive>
</receives>

我希望按年份分组,如果年份不在列表中(如上面的xml,没有2011年),我需要将2012年的结果与totalamount = 0进行如下:

<year>2011</year>
<totalamount>120</totalamount>
<year>2012</year>
<totalamount>0</totalamount>
<year>2013</year>
<totalamount>270</totalamount>
<year>2014</year>
<totalamount>130</totalamount>

当然,我已完成xslt如下:     

<xsl:key name="receive-key" match="receive" use="Year" />

<xsl:template match="/receives">
    <xsl:for-each
        select="receive[generate-id() = generate-id(key('receive-key', Year))]">
            <xsl:sort select="../receive[Year = current()/Year]/Year"></xsl:sort>
            <year>
                <xsl:value-of select="../receive[Year = current()/Year]/Year" />
            </year>
            <totalamount>
                <xsl:value-of select="sum(../receive[Year = current()/Year]/money)" />
            </totalamount>
    </xsl:for-each>
</xsl:template>

这只能按现有年度分组:

<year>2011</year>
<totalamount>120</totalamount> 
<year>2013</year>
<totalamount>270</totalamount>
<year>2014</year>
<totalamount>130</totalamount>

关于如何插入

的任何想法
<year>2012</year>
<totalamount>0</totalamount> 

进入结果?

非常感谢!

1 个答案:

答案 0 :(得分:2)

执行此操作的一种方法可能是使用命名模板,该模板使用一年的参数调用。如果密钥中不存在今年,则输出一个空值,并在下一年调用它。

<xsl:template name="Year">
   <xsl:param name="Year"/>
   <xsl:if test="not(key('receive-key', $Year))">
      <year>
         <xsl:value-of select="$Year"/>
      </year>
      <totalamount>0</totalamount>
      <xsl:call-template name="Year">
         <xsl:with-param name="Year" select="$Year + 1"/>
      </xsl:call-template>
   </xsl:if>
</xsl:template>

因此,一旦在密钥中找到一年,它就会停止输出缺失的年份。

另外需要注意的是,XSLT中的一个表达式

<xsl:value-of select="../receive[Year = current()/Year]/Year" />

这实际上可以简化为这个!

<xsl:value-of select="Year"/>

同样,您可以更改总和以使用 xsl:key 提高效率

<xsl:value-of select="sum(key('receive-key', Year)/money)"/>

这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:key name="receive-key" match="receive" use="Year"/>

   <xsl:template match="/receives">
      <xsl:for-each select="receive[generate-id() = generate-id(key('receive-key', Year))]">
         <xsl:sort select="Year"/>
         <year>
            <xsl:value-of select="Year"/>
         </year>
         <totalamount>
            <xsl:value-of select="sum(key('receive-key', Year)/money)"/>
         </totalamount>
         <xsl:if test="position() != last()">
            <xsl:call-template name="Year">
               <xsl:with-param name="Year" select="number(Year) + 1"/>
            </xsl:call-template>
         </xsl:if>
      </xsl:for-each>
   </xsl:template>

   <xsl:template name="Year">
      <xsl:param name="Year"/>
      <xsl:if test="not(key('receive-key', $Year))">
         <year>
            <xsl:value-of select="$Year"/>
         </year>
         <totalamount>0</totalamount>
         <xsl:call-template name="Year">
            <xsl:with-param name="Year" select="$Year + 1"/>
         </xsl:call-template>
      </xsl:if>
   </xsl:template>
</xsl:stylesheet>

应用于XML时,输出以下内容

<year>2011</year>
<totalamount>120</totalamount>
<year>2012</year>
<totalamount>0</totalamount>
<year>2013</year>
<totalamount>270</totalamount>
<year>2014</year>
<totalamount>130</totalamount>