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

如何用XSLT 1.0拆分支付历史字符串?解决XML节点重复问题

解决XSLT 1.0支付历史字符串分组去重问题

我来帮你搞定这个重复节点的问题!在XSLT 1.0里处理这种按年份分组的需求,Muenchian分组法是最靠谱的方案——这正是解决你当前重复节点问题的核心。

先明确需求场景

假设你的输入字符串是这样的(模拟示例):
Apr:2013,1200/STD|Mar:2013,900/STD|Dec:2012,800/STD|Mar:2012,750/STD|

我们需要输出的XML结构应该是:

<Periods>
  <Period year="2013">
    <Months month="Apr" value="1200/STD"/>
    <Months month="Mar" value="900/STD"/>
  </Period>
  <Period year="2012">
    <Months month="Dec" value="800/STD"/>
    <Months month="Mar" value="750/STD"/>
  </Period>
</Periods>

问题根源:未正确分组

你之前的实现出现重复节点,大概率是因为每次处理单个月份条目时都生成了<Period>节点,而没有先按年份去重,再将同一年的月份归到同一个<Period>下。

解决方案:Muenchian分组+字符串拆分

下面是完整的XSLT 1.0代码,包含字符串拆分、分组逻辑,完全解决重复问题:

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

  <!-- 定义Muenchian分组的键:按年份分组 -->
  <xsl:key name="year-group" match="entry" use="@year"/>

  <xsl:template match="/">
    <Periods>
      <!-- 先拆分输入字符串为单个条目节点 -->
      <xsl:call-template name="split-entries">
        <xsl:with-param name="input" select="'Apr:2013,1200/STD|Mar:2013,900/STD|Dec:2012,800/STD|Mar:2012,750/STD|'"/>
      </xsl:call-template>

      <!-- 处理分组:获取所有唯一的年份 -->
      <xsl:for-each select="entry[generate-id() = generate-id(key('year-group', @year)[1])]">
        <!-- 按年份排序(可选,让输出更规整) -->
        <xsl:sort select="@year" order="descending"/>
        <Period year="{@year}">
          <!-- 遍历当前年份下的所有条目 -->
          <xsl:for-each select="key('year-group', @year)">
            <!-- 按月份排序(可选) -->
            <xsl:sort select="translate(@month, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', '0123456789ABCDEFGHIJKLMNOPQRSTUV')"/>
            <Months month="{@month}" value="{@value}"/>
          </xsl:for-each>
        </Period>
      </xsl:for-each>
    </Periods>
  </xsl:template>

  <!-- 递归模板:拆分|分隔的条目 -->
  <xsl:template name="split-entries">
    <xsl:param name="input"/>
    <xsl:if test="$input != ''">
      <!-- 获取第一个|之前的条目 -->
      <xsl:variable name="entry" select="substring-before($input, '|')"/>
      <xsl:if test="$entry != ''">
        <!-- 拆分条目为月份年份和值 -->
        <xsl:call-template name="parse-entry">
          <xsl:with-param name="entry" select="$entry"/>
        </xsl:call-template>
      </xsl:if>
      <!-- 递归处理剩余部分 -->
      <xsl:call-template name="split-entries">
        <xsl:with-param name="input" select="substring-after($input, '|')"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

  <!-- 解析单个条目:拆分月份年份和值 -->
  <xsl:template name="parse-entry">
    <xsl:param name="entry"/>
    <xsl:variable name="month-year" select="substring-before($entry, ',')"/>
    <xsl:variable name="value" select="substring-after($entry, ',')"/>
    <entry 
      month="{substring-before($month-year, ':')}" 
      year="{substring-after($month-year, ':')}" 
      value="{$value}"/>
  </xsl:template>
</xsl:stylesheet>

代码解释

  1. Muenchian分组键:key('year-group', @year) 用来将所有同一年的entry节点归为一组,通过generate-id()判断是否是组内第一个节点,从而实现去重。
  2. 字符串拆分:通过两个递归模板,先拆分|分隔的条目,再拆分每个条目中的,分隔部分,提取月份、年份和值,生成临时的entry节点。
  3. 排序逻辑:可选的排序模板让年份从新到旧,月份按自然顺序排列,让输出结构更规整。
  4. 避免重复:先遍历唯一的年份,再为每个年份生成单个<Period>,然后将该年份下的所有月份条目作为子节点,彻底解决重复问题。

输出结果

运行上述XSLT后,会生成开头展示的规整XML结构,完全没有重复的<Period>节点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:38:02