【问题标题】:XSLT for grouping and summing valuesXSLT 用于对值进行分组和求和
【发布时间】:2013-02-13 06:48:57
【问题描述】:

我是 XSLT 的新手,无法完成结果,我来到这里以防有人可以帮助我。

我有以下 XML:

<funds>
    <bags>
        <bag name="BAG_USD_MAIN" value="10.0" type="USD">
            <pockets>
                <pocket name="bank" value="7.5">
                <pocket name="award" value="2.5">
            </pockets>
         </bag>
        <bag name="BAG_USD_SAVINGS" value="290.75" type="USD">
            <pockets>
                <pocket name="bank" value="290.75">
            </pockets>
         </bag>
        <bag name="BAG_EUR_EXTRA" value="890.0" type="EUR">
            <pockets>
                <pocket name="bank" value="753.0">
                <pocket name="bank_eng" value="137.0">
            </pockets>
         </bag>
    </bags>
 </funds>

我希望能够以这种方式对其进行改造:

<result>
    <total type="USD">375.0</total>
    <total type="EUR">890.0</total>
</result>

XSLT 可以吗?

谢谢, 问候 TS

【问题讨论】:

  • 那就是 XSLT 2.0。

标签: xml xslt xslt-2.0


【解决方案1】:

因为您使用的是 XSLT 2.0,您可以使用 元素按 @type 对元素进行分组,然后使用 sum() 对组中的元素求和。

以下样式表解决了您正在尝试做的事情:

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


    <!-- Match the bags element  -->
    <xsl:template match="bags">
        <result>
            <!-- Group each bag element by its type -->
            <xsl:for-each-group select="bag" group-by="@type">
                <!-- Use the current key to display the type attribute -->
                <total type="{current-grouping-key()}">
                    <!-- Sum all the elements from the current group -->
                    <xsl:value-of select="sum(current-group()/@value)" />
                </total>
            </xsl:for-each-group>
        </result>
    </xsl:template>

</xsl:stylesheet>

为了完整性,XSLT 1.0 解决方案将基于 Muenchian 分组。

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

    <!-- Index all bag elements withing bags element using their
         type attribute by using a key -->
    <xsl:key name="currency-key"
             match="/funds/bags/bag"
             use="@type" />

    <!-- Match bags element -->
    <xsl:template match="bags">
        <result>
            <!-- Match the first bag element for a specific group -->
            <xsl:apply-templates select="bag[generate-id() = generate-id(key('currency-key', @type)[1])]" />
        </result>
    </xsl:template>

    <xsl:template match="bag">
        <total type="{@type}">
            <!-- Sum all the elements from the @type group -->
            <xsl:value-of select="sum(key('currency-key', @type)/@value)" />
        </total>
    </xsl:template>

</xsl:stylesheet>

【讨论】:

    【解决方案2】:

    是的。我手边没有 XSLT 处理器,但可以尝试以下方法:

    <result>
      <xsl:for-each select="distinct-values(//bag/@type)">
        <total type="."><xsl:value-of select="sum(//bag[@type = .])"/></total>
      </xsl:for-each>
    </result>
    

    对于大量数据,您应该考虑改用&lt;xsl:for-each-group&gt;

    【讨论】:

    • 如果数据大小不一,这不仅仅是品味问题:for-each-group 解决方案可能要快得多。
    猜你喜欢
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    • 2017-05-12
    • 1970-01-01
    相关资源
    最近更新 更多