You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

适配.NET编译器:无key函数的XSLT 1.0代码生成指定PremiumSplit

XSLT 1.0 无key函数分组聚合实现方案

针对.NET环境无法使用key()函数的限制,以下代码通过排序+相邻节点比较的方式替代Muenchian分组,满足所有需求:

实现逻辑

  1. 先将所有Record节点按CoverageSection、CoverageCode、VehicleCategory排序,确保同组节点连续排列
  2. 遍历节点时,仅处理每组的第一个节点(通过对比当前节点与前一节点的分组键判断),避免重复输出
  3. 对每个分组,通过节点路径筛选计算对应保费总和及占比,同时处理除零异常

完整XSLT代码

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

    <!-- 主入口:排序所有Record节点 -->
    <xsl:template match="/">
        <Result>
            <xsl:apply-templates select="/*/Record">
                <xsl:sort select="CoverageSection" data-type="text"/>
                <xsl:sort select="CoverageCode" data-type="text"/>
                <xsl:sort select="VehicleCategory" data-type="text"/>
            </xsl:apply-templates>
        </Result>
    </xsl:template>

    <!-- 仅输出每组的第一个节点 -->
    <xsl:template match="Record">
        <xsl:variable name="currentKey" select="concat(CoverageSection, '|', CoverageCode, '|', VehicleCategory)"/>
        <xsl:variable name="prevKey" select="preceding-sibling::Record[1]/concat(CoverageSection, '|', CoverageCode, '|', VehicleCategory)"/>

        <xsl:if test="not($prevKey = $currentKey)">
            <xsl:call-template name="processGroup">
                <xsl:with-param name="section" select="CoverageSection"/>
                <xsl:with-param name="code" select="CoverageCode"/>
                <xsl:with-param name="category" select="VehicleCategory"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

    <!-- 分组统计与输出模板 -->
    <xsl:template name="processGroup">
        <xsl:param name="section"/>
        <xsl:param name="code"/>
        <xsl:param name="category"/>

        <!-- 计算当前分类下的保费总和 -->
        <xsl:variable name="categoryPremium" select="sum(//Record[CoverageSection = $section and CoverageCode = $code and VehicleCategory = $category]/Premium)"/>
        <!-- 计算当前CoverageCode的总保费 -->
        <xsl:variable name="codeTotalPremium" select="sum(//Record[CoverageSection = $section and CoverageCode = $code]/Premium)"/>

        <!-- 计算保费占比,处理除零情况 -->
        <xsl:variable name="coveragePercent">
            <xsl:choose>
                <xsl:when test="$codeTotalPremium = 0 or $codeTotalPremium = ''">0.00%</xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="format-number($categoryPremium div $codeTotalPremium, '0.00%')"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>

        <CoverageGroup>
            <CoverageSection><xsl:value-of select="$section"/></CoverageSection>
            <CoverageCode><xsl:value-of select="$code"/></CoverageCode>
            <VehicleCategory><xsl:value-of select="$category"/></VehicleCategory>
            <CategoryPremium><xsl:value-of select="$categoryPremium"/></CategoryPremium>
            <CodeTotalPremium><xsl:value-of select="$codeTotalPremium"/></CodeTotalPremium>
            <CoveragePercent><xsl:value-of select="$coveragePercent"/></CoveragePercent>
        </CoverageGroup>
    </xsl:template>

    <!-- 忽略无关文本节点 -->
    <xsl:template match="text()"/>
</xsl:stylesheet>

关键细节说明

  • 去重逻辑:通过拼接三个分组字段生成唯一键,对比当前节点与前一节点的键值,仅处理新组的第一个节点,确保每组只输出一次
  • 保费统计:使用sum()函数结合节点筛选路径,精准计算同Section下的分类保费和Code总保费
  • 异常处理:通过xsl:choose判断总保费是否为0,避免除法运算出现错误,将无穷大/NaN替换为0.00%
  • 性能优化:如果原XML中Record有明确的父节点,建议将//Record替换为具体的相对路径(如../Record),减少全局遍历开销

内容的提问来源于stack exchange,提问作者user1635003

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:30:02