XSLT 2组和总和值

时间:2013-03-17 12:23:36

标签: xslt sum grouping xslt-2.0

我正在尝试使用XSLT 2.0来汇总每个Year / YearQtr的产品[Widgets]的所有个人销售人员[VOL],按其salesteam,department进行分组。可能有多种产品类型,我在这里只留下一种类型来尝试简化代码。

  1. 我设法使用for-each获取特定年份的YearQtr值列表,但我无法弄清楚如何获得所有Year和YearQtr元素的明显列表,这些元素显示为销售员/性能。
  2. 我尝试过currentgroup(),但是无法看到如何指定分组,以便我只获得部门级别的总和,而不是每个SalesPerson。
  3. 我正在使用的XML是:

    <salesteam id="Team1">
        <department id="dept1">
            <salespeople>
                <salesperson id="98765">
                    <performance>
                        <year id="2013">
                            <yearqtr id="1">
                                <yearMonth id="1">
                                    <products>
                                        <widgets>
                                            <vol>5</vol>
                                            <val>50000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                                <yearMonth id="2">
                                    <products>
                                        <widgets>
                                            <vol>10</vol>
                                            <val>100000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                                <yearMonth id="3">
                                    <products>
                                        <widgets>
                                            <vol>15</vol>
                                            <val>150000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                            </yearqtr>
                            <yearqtr id="2">
                                <yearMonth id="4">
                                    <products>
                                        <widgets>
                                            <vol>20</vol>
                                            <val>200000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                                <yearMonth id="5">
                                    <products>
                                        <widgets>
                                            <vol>25</vol>
                                            <val>250000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                                <yearMonth id="6">
                                    <products>
                                        <widgets>
                                            <vol>30</vol>
                                            <val>300000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                            </yearqtr>
                        </year>
                    </performance>
                </salesperson>
                <salesperson id="12345">
                    <performance>
                        <year id="2013">
                            <yearqtr id="1">
                                <yearMonth id="1">
                                    <products>
                                        <widgets>
                                            <vol>5</vol>
                                            <val>50000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                                <yearMonth id="2">
                                    <products>
                                        <widgets>
                                            <vol>10</vol>
                                            <val>100000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                                <yearMonth id="3">
                                    <products>
                                        <widgets>
                                            <vol>15</vol>
                                            <val>150000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                            </yearqtr>
                            <yearqtr id="2">
                                <yearMonth id="4">
                                    <products>
                                        <widgets>
                                            <vol>20</vol>
                                            <val>200000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                                <yearMonth id="5">
                                    <products>
                                        <widgets>
                                            <vol>25</vol>
                                            <val>250000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                                <yearMonth id="6">
                                    <products>
                                        <widgets>
                                            <vol>30</vol>
                                            <val>300000</val>
                                        </widgets>
                                    </products>
                                </yearMonth>
                            </yearqtr>
                        </year>
                    </performance>
                </salesperson>
            </salespeople>
        </department>
    </salesteam>
    

    我想要实现的是

    <table>
    <tbody>
    <tr>
    <th>2013Q1</th>
    <th>2013Q2</th>
    <th>2013Q3</th>
    <th>2013Q4</th>
    </tr>
    <tr>
    <td>30</td>
    <td>75</td>
    <td>0</td>
    <td>0</td>
    </tr>
    </tbody>
    </table>
    

1 个答案:

答案 0 :(得分:0)

你真的需要在这里使用分组吗?如果您可以安全地假设一年中总共有四个季度,那么您可以只使用总和语句来总结给定季度和年份的所有窗口小部件卷,如此(其中$ year是持有年份的参数,以及$ qtr持有季度)

<xsl:value-of select="sum(//year[@id=$year]/yearqtr[@id=$qtr]/yearMonth/products/widgets/vol)" />

你可以把它放在一个命名模板中,以 qtr 作为参数,然后调用它四次

<xsl:call-template name="sum"><xsl:with-param name="qtr" select="1" /></xsl:call-template>
<xsl:call-template name="sum"><xsl:with-param name="qtr" select="2" /></xsl:call-template>
<xsl:call-template name="sum"><xsl:with-param name="qtr" select="3" /></xsl:call-template>
<xsl:call-template name="sum"><xsl:with-param name="qtr" select="4" /></xsl:call-template>

虽然使用密钥查找特定年份和季度的小部件可能会稍微清洁一些,效率更高。

<xsl:key name="quarters" match="yearqtr" use="concat(../@id, '|', @id)"/>

然后你的总和就变成了这个

<xsl:value-of 
     select="sum(key('quarters', concat($year, '|', $qtr))/yearMonth/products/widgets/vol)"/>

在这种情况下,这是完整的XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:key name="quarters" match="yearqtr" use="concat(../@id, '|', @id)"/>

   <xsl:param name="year" select="2013"/>

   <xsl:template match="/*">
      <table>
         <tbody>
            <tr>
               <th><xsl:value-of select="$year"/>Q1</th>
               <th><xsl:value-of select="$year"/>Q2</th>
               <th><xsl:value-of select="$year"/>Q3</th>
               <th><xsl:value-of select="$year"/>Q4</th>
            </tr>
            <tr>
               <xsl:call-template name="sum"><xsl:with-param name="qtr" select="1" /></xsl:call-template>
               <xsl:call-template name="sum"><xsl:with-param name="qtr" select="2" /></xsl:call-template>
               <xsl:call-template name="sum"><xsl:with-param name="qtr" select="3" /></xsl:call-template>
               <xsl:call-template name="sum"><xsl:with-param name="qtr" select="4" /></xsl:call-template>
            </tr>
         </tbody>
      </table>
   </xsl:template>

   <xsl:template name="sum">
      <xsl:param name="qtr"/>
      <td>
         <xsl:value-of select="sum(key('quarters', concat($year, '|', $qtr))/yearMonth/products/widgets/vol)"/>
      </td>
   </xsl:template>
</xsl:stylesheet>

如果您确实想要使用分组,那么您将在XSLT2.0中执行此操作

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:param name="year" select="2013"/>

   <xsl:template match="/*">
      <table>
         <tbody>
            <tr>
               <xsl:for-each-group select="//year[@id=$year]/yearqtr" group-by="@id">
                    <td><xsl:value-of select="concat($year, 'Q', current-grouping-key())" /></td>
               </xsl:for-each-group>
            </tr>
            <tr>
               <xsl:for-each-group select="//year[@id=$year]/yearqtr" group-by="@id">
                    <td><xsl:value-of select="sum(current-group()/yearMonth/products/widgets/vol)"/></td>
               </xsl:for-each-group>
            </tr>
         </tbody>
      </table>
   </xsl:template>
</xsl:stylesheet>

这只会显示存在的季度,所以如果第四季度没有 yearqtr 元素,那么只会显示第1到第3季度。

编辑:如果你有多年,那么假设你仍然希望它们在不同的列上,你会像这样进行分组:

<xsl:for-each-group select="//yearqtr" group-by="concat(../@id, 'Q', @id)">

在这种情况下,这是完整的XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/*">
      <table>
         <tbody>
            <tr>
               <xsl:for-each-group select="//yearqtr" group-by="concat(../@id, 'Q', @id)">
                    <td><xsl:value-of select="current-grouping-key()" /></td>
               </xsl:for-each-group>
            </tr>
            <tr>
               <xsl:for-each-group select="//yearqtr" group-by="concat(../@id, 'Q', @id)">
                    <td><xsl:value-of select="sum(current-group()/yearMonth/products/widgets/vol)"/></td>
               </xsl:for-each-group>
            </tr>
         </tbody>
      </table>
   </xsl:template>
</xsl:stylesheet>