XSLT 1.0 Group和Sum by values

时间:2018-04-11 14:03:11

标签: xml xslt sum

我正在努力做一个小组和总结。我有这个xml:

<articles>
<group>
  <code>1000</code>
  <description>GROUP A</description>
  <article>
    <code>2600</code>
    <description>Article A</description>        
    <qty>14.00</qty>
    <amount>14.00</amount>        
    <menu_code>true</menu_code>
  </article>
  <article>
    <code>2600</code>
    <description>Article A</description>
    <qty>10.00</qty>
    <amount>0.00</amount>        
    <menu_code>true</menu_code>
  </article>
  <article>
    <code>2600</code>
    <description>Article A</description>
    <qty>1.00</qty>
    <amount>1.00</amount>        
    <menu_code>false</menu_code>
  </article>
</group>
<group>
  <code>2000</code>
  <description>GROUP B</description>
  <article>
    <code>2600</code>
    <description>Article B</description>        
    <qty>28.00</qty>
    <amount>28.00</amount>        
    <menu_code>true</menu_code>
  </article>
  <article>
    <code>2600</code>
    <description>Article B</description>
    <qty>10.00</qty>
    <amount>27.00</amount>        
    <menu_code>false</menu_code>
  </article>
  <article>
    <code>2600</code>
    <description>Article B</description>
    <qty>4.00</qty>
    <amount>8.00</amount>        
    <menu_code>false</menu_code>
  </article>
</group>

有了这些数据,我需要展示这样的东西:

GROUP A

A条数量:24总计:14.00

A条*数量:1总计:1.00

B组

B条数量:28总计:28.00

B条*数量:14总计:35.00

显示按组排序的数据(文章/组) 然后显示文章描述(文章/描述),数量总和(总和(数量))和总和(总和(数量))。 如果文章有(article / menu_code = true),则显示在另一行中,与false(*)

分开

希望你能帮助我,谢谢!

1 个答案:

答案 0 :(得分:0)

在XSLT 1.0中,可以通过称为Muenchian Grouping的技术实现分组。

在您的示例中,由于要根据<article><description><menu_code>值进行分组,因此需要定义一个密钥,该密钥将是<description>的组合和<menu_code>

<xsl:key name="kArticle" match="article" use="concat(description, '|', menu_code)" />

下一步是使用密钥和节点ID对<article>个节点进行分组。这将仅选择适当分组的节点。

<xsl:template match="article[generate-id() = generate-id(key('kArticle', concat(description, '|', menu_code))[1])]">

其余<article>个节点将保持未处理状态。

<xsl:template match="article" />

以下是分别用于XML输出和HTML输出的2个不同的XSLT。基础分组概念是相同的,更改仅与输出的显示方式有关。

XSLT - XML输出

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" />
    <xsl:strip-space elements="*" />

    <xsl:key name="kArticle" match="article" use="concat(description, '|', menu_code)" />

    <!-- identity transform -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="article[generate-id() = generate-id(key('kArticle', concat(description, '|', menu_code))[1])]">
        <xsl:copy>
            <xsl:apply-templates select="description" />
            <totalQty>
                <xsl:value-of select="sum(key('kArticle', concat(description, '|', menu_code))/qty)" />
            </totalQty>
            <totalAmount>
                <xsl:value-of select="format-number(sum(key('kArticle', concat(description, '|', menu_code))/amount),'#.00')" />
            </totalAmount>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="article" />
</xsl:stylesheet>

XML输出

<articles>
    <group>
        <code>1000</code>
        <description>GROUP A</description>
        <article>
            <description>Article A</description>
            <totalQty>24</totalQty>
            <totalAmount>14.00</totalAmount>
        </article>
        <article>
            <description>Article A</description>
            <totalQty>1</totalQty>
            <totalAmount>1.00</totalAmount>
        </article>
    </group>
    <group>
        <code>2000</code>
        <description>GROUP B</description>
        <article>
            <description>Article B</description>
            <totalQty>28</totalQty>
            <totalAmount>28.00</totalAmount>
        </article>
        <article>
            <description>Article B</description>
            <totalQty>14</totalQty>
            <totalAmount>35.00</totalAmount>
        </article>
    </group>
</articles>

XSLT - HTML输出

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" />
    <xsl:strip-space elements="*" />

    <xsl:key name="kArticle" match="article" use="concat(description, '|', menu_code)" />

    <xsl:template match="articles">
        <html>
            <body>
                <xsl:for-each select="group">
                    <h3><xsl:value-of select="description" /></h3>
                    <table border="1" cellspacing="0" cellpadding="3">
                        <tr>
                            <th>Article Description</th>
                            <th>Total Quantity</th>
                            <th>Total Amount</th>
                        </tr>
                        <xsl:apply-templates select="article" />
                    </table>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="article[generate-id() = generate-id(key('kArticle', concat(description, '|', menu_code))[1])]">
        <tr>
            <td>
                <xsl:value-of select="description" />
            </td>
            <td>
                <xsl:value-of select="sum(key('kArticle', concat(description, '|', menu_code))/qty)" />
            </td>
            <td>
                <xsl:value-of select="format-number(sum(key('kArticle', concat(description, '|', menu_code))/amount),'#.00')" />
            </td>
        </tr>
    </xsl:template>
    <xsl:template match="article" />
</xsl:stylesheet>

HTML输出

HTML Tabular Output