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

XSLT 2.0按ID属性合并节点 将J开头ID节点归入新父节点

XSLT 2.0 按ID前缀分组合并节点实现方案

问题根因

  • 原代码模板匹配路径错误:源XML中Row节点的父容器是RepData,原代码写为匹配/Rep/Report,无法选中目标节点
  • 原分组逻辑直接以完整ID值为分组键,没有先按「ID是否以J开头」做第一层分桶,无法将J开头的节点归集到同一父节点下
  • 原代码拼接层级id时直接用逗号连接值,不符合父路径逐层拼接的要求

修正后完整XSLT代码

<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- 修正匹配路径,命中正确的RepData节点 -->
  <xsl:template match="/Rep/RepData">
    <ccs>
      <!-- 第一层分组:J开头ID归为一组,其余ID各自保留独立分组逻辑 -->
      <xsl:for-each-group select="Row" group-by="starts-with(Field[@name='ID'], 'J')">
        <xsl:choose>
          <!-- 处理J开头ID分组,生成统一父ccwc节点 -->
          <xsl:when test="current-grouping-key() = true()">
            <ccwc id="1-J">
              <name>One J</name>
              <cccs>
                <!-- 组内按原规则按ID做第二层分组 -->
                <xsl:for-each-group select="current-group()" group-by="Field[@name='ID']">
                  <xsl:variable name="ref" select="current-grouping-key()"/>
                  <ccwc id="{concat('1-J/', $ref)}">
                    <name>
                      <xsl:value-of select="if (string-length(Field[@name='CName']) != 0) then Field[@name='CName'] else 'Unknown'"/>
                    </name>
                    <cccs>
                      <!-- 第三层按GPL分组,保持原有ccc节点生成规则 -->
                      <xsl:for-each-group select="current-group()" group-by="Field[@name='GPL']">
                        <xsl:variable name="childRef" select="current-grouping-key()"/>
                        <ccc id="{concat('1-J/', $ref, '/', $childRef)}">
                          <name><xsl:value-of select="$childRef"/></name>
                        </ccc>
                      </xsl:for-each-group>
                    </cccs>
                  </ccwc>
                </xsl:for-each-group>
              </cccs>
            </ccwc>
          </xsl:when>
          <!-- 处理非J开头ID,完全保留原有输出结构 -->
          <xsl:otherwise>
            <xsl:for-each-group select="current-group()" group-by="Field[@name='ID']">
              <xsl:variable name="ref" select="current-grouping-key()"/>
              <ccwc id="{$ref}">
                <name>
                  <xsl:value-of select="if (string-length(Field[@name='CName']) != 0) then Field[@name='CName'] else 'Unknown'"/>
                </name>
                <cccs>
                  <xsl:for-each-group select="current-group()" group-by="Field[@name='GPL']">
                    <xsl:variable name="childRef" select="current-grouping-key()"/>
                    <ccc id="{concat($ref, '/', $childRef)}">
                      <name><xsl:value-of select="$childRef"/></name>
                    </ccc>
                  </xsl:for-each-group>
                </cccs>
              </ccwc>
            </xsl:for-each-group>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each-group>
    </ccs>
  </xsl:template>
</xsl:transform>

关键调整点说明

  • 修正模板匹配路径:将原错误的/Rep/Report改为源XML实际存在的/Rep/RepData,保证模板能正确命中目标节点
  • 新增第一层分组逻辑:以starts-with(Field[@name='ID'], 'J')作为分组键,所有J开头的Row会被归集到同一分组,非J开头的Row归集到另一分组
  • 针对J开头的分组,单独生成固定属性的父级ccwc节点:id固定为1-J,name固定为One J;组内所有J开头的Row沿用原有的ID、GPL两层分组规则生成子节点,所有子节点的id从父节点id开始逐层拼接
  • 非J开头的分组内,完全沿用原有的按ID、GPL两层分组逻辑,输出结构和规则保持一致,id按自身路径拼接
  • 用XSLT 2.0原生支持的属性值模板(AVT)、if表达式简化冗余的变量定义和条件判断,提升代码可读性和执行效率

输出结构说明

转换后根节点<ccs>下共生成3个平级的一级ccwc节点:

  • id为A的ccwc节点,对应ID=A的非J类Row,内部结构和原规则一致
  • id为1-J的ccwc节点,其<cccs>子节点下挂载J-A、J-U、J-I三个二级ccwc节点,每个二级ccwc下再按GPL规则挂载对应的ccc节点,所有节点id从父级开始逐层拼接
  • id为M的ccwc节点,对应ID=M的非J类Row,内部结构和原规则一致

如果需要调整id拼接的分隔符,直接修改concat()函数中的连接参数即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:06:44