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

基于ALF、OND分组K18并按指定顺序排列子段的XSLT问题

解决方案

1. XSLT 1.0 兼容的Muenchian分组实现

先定义分组键,用ALF和OND的组合值来分组K18段:

<xsl:key name="k18Group" match="K18" use="concat(ALF, '|', OND)" />

然后处理每个分组的首个K18节点,把同组的所有子段按指定顺序整合到新的K18里:

<!-- 遍历每个K18分组的第一个节点 -->
<xsl:for-each select="K18[generate-id() = generate-id(key('k18Group', concat(ALF, '|', OND))[1])]">
  <K18>
    <!-- 保留当前分组的ALF和OND字段 -->
    <xsl:copy-of select="ALF | OND" />
    
    <!-- 严格按 P04Y → P04Z → P04 → P03 的顺序输出子段 -->
    <xsl:copy-of select="key('k18Group', concat(ALF, '|', OND))/P04Y" />
    <xsl:copy-of select="key('k18Group', concat(ALF, '|', OND))/P04Z" />
    <xsl:copy-of select="key('k18Group', concat(ALF, '|', OND))/P04" />
    <xsl:copy-of select="key('k18Group', concat(ALF, '|', OND))/P03" />
  </K18>
</xsl:for-each>

这种方法不用依赖sort函数,直接按你要的顺序挨个提取对应子段就行——要是某个子段不存在,copy-of不会输出任何内容,自动忽略掉了。

2. XSLT 2.0+ 简化分组实现

如果用的是XSLT 2.0及以上版本,用xsl:for-each-group会更简洁:

<xsl:for-each-group select="K18" group-by="concat(ALF, '|', OND)">
  <K18>
    <!-- 取分组内第一个节点的ALF和OND(同组值一致) -->
    <xsl:copy-of select="current-group()[1]/ALF | current-group()[1]/OND" />
    
    <!-- 按指定顺序输出子段 -->
    <xsl:copy-of select="current-group()/P04Y" />
    <xsl:copy-of select="current-group()/P04Z" />
    <xsl:copy-of select="current-group()/P04" />
    <xsl:copy-of select="current-group()/P03" />
  </K18>
</xsl:for-each-group>

3. 解决分组内容被放到最后的问题

你之前的XSLT把分组内容放最后,大概率是因为在处理完所有其他段之后才输出分组后的K18。要避免这个问题,可以这么做:

  • 先按原顺序输出所有非K18的段
  • 再输出分组后的K18;或者如果要保留K18在原上下文的位置,就遍历所有节点时,遇到分组的第一个K18就输出整合后的内容,跳过同组其他K18。

示例(保留非K18段的原顺序,替换所有K18为分组结果):

<xsl:template match="/*">
  <xsl:copy>
    <!-- 先输出所有非K18的节点,保持原顺序 -->
    <xsl:apply-templates select="node()[not(self::K18)]" />
    
    <!-- 输出分组后的K18段 -->
    <xsl:for-each select="K18[generate-id() = generate-id(key('k18Group', concat(ALF, '|', OND))[1])]">
      <K18>
        <xsl:copy-of select="ALF | OND" />
        <xsl:copy-of select="key('k18Group', concat(ALF, '|', OND))/P04Y" />
        <xsl:copy-of select="key('k18Group', concat(ALF, '|', OND))/P04Z" />
        <xsl:copy-of select="key('k18Group', concat(ALF, '|', OND))/P04" />
        <xsl:copy-of select="key('k18Group', concat(ALF, '|', OND))/P03" />
      </K18>
    </xsl:for-each>
  </xsl:copy>
</xsl:template>

<!-- 空模板跳过原K18节点,防止重复输出 -->
<xsl:template match="K18" />

关键提醒

别用普通的xsl:sort按节点名称排序,因为字母顺序是P03 < P04 < P04Y < P04Z,刚好和你要的顺序相反。直接按指定顺序提取子段才是最稳妥的方式,而且天然支持可选段——没有的段会自动被忽略,不用额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:04:55