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

XSLT的for-each-group基于双字段分组失效问题求助

OIC中XSLT按双元素分组去重的问题解决

问题背景

在OIC应用中使用XSLT处理XML数据,需要基于DOC和DOCO两个元素的组合过滤重复记录,仅保留每组的第一条记录,但原有的分组代码未生效,无法得到预期的去重结果。

输入XML结构

<?xml version='1.0' encoding='UTF-8'?>
<SyncFileResponse xmlns="http://xmlns.oracle.com/types">
      <AFiles xmlns="http://TargetNamespace.com/fileReference">
         <AFile>
            <DOC>DOC1</DOC>
            <DOCO>DOC1</DOCO>
            <DCTO>DCTO1</DCTO>
            <GRWT>GRWT1</GRWT>
            <GWUM>GWUM1</GWUM>
            <Column31>Column31616968</Column31>
         </AFile>
         <AFile>
            <DOC>DOC1</DOC>
            <DOCO>DOC1</DOCO>
            <DCTO>DCTO10</DCTO>
            <GRWT>GRWT10</GRWT>
            <GWUM>GWUM10</GWUM>
            <Column31>ABCD0</Column31>
         </AFile>
         <AFile>
            <DOC>DOC2</DOC>
            <DOCO>DOC2</DOCO>
            <DCTO>DCTO2</DCTO>
            <GRWT>GRWT2</GRWT>
            <GWUM>GWUM2</GWUM>
            <Column31>ABCD2</Column31>
         </AFile>
         <AFile>
            <DOC>DOC2</DOC>
            <DOCO>DOC2</DOCO>
            <DCTO>DCTO20</DCTO>
            <GRWT>GRWT20</GRWT>
            <GWUM>GWUM20</GWUM>
            <Column31>ABCD20</Column31>
         </AFile>
      </AFiles>
</SyncFileResponse>

尝试的分组代码

<xsl:for-each-group select="$FileFromInprogress/nsmpr1:SyncFileResponse/ns20:AFiles/ns20:AFile" group-by="concat (ns20:DOC, ns20:DOCO )">

预期输出

<AFile>
  <DOC>DOC1</DOC>
  <DOCO>DOC1</DOCO>
  <DCTO>DCTO1</DCTO>
  <GRWT>GRWT1</GRWT>
  <GWUM>GWUM1</GWUM>
  <Column31>Column31616968</Column31>
</AFile>
            
<AFile>
  <DOC>DOC2</DOC>
  <DOCO>DOC2</DOCO>
  <DCTO>DCTO2</DCTO>
  <GRWT>GRWT2</GRWT>
  <GWUM>GWUM2</GWUM>
  <Column31>ABCD2</Column31>
</AFile>

替代解决方案

方案1:使用多键分组(XSLT 2.0+,OIC支持)

原代码用concat拼接两个元素值分组,可能出现意外匹配(比如DOC="AB"+DOCO="CD"和DOC="A"+DOCO="BCD"会被判定为同一组),更可靠的方式是直接用多键分组:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:nsmpr1="http://xmlns.oracle.com/types"
    xmlns:ns20="http://TargetNamespace.com/fileReference"
    exclude-result-prefixes="nsmpr1 ns20">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
        <xsl:variable name="FileFromInprogress" select="."/>
        <xsl:for-each-group select="$FileFromInprogress/nsmpr1:SyncFileResponse/ns20:AFiles/ns20:AFile" 
                            group-by="(ns20:DOC, ns20:DOCO)">
            <!-- 输出每组的第一个AFile元素 -->
            <xsl:copy-of select="current-group()[1]"/>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

方案2:Muenchian分组(兼容XSLT 1.0)

如果环境限制只能用XSLT 1.0,可以用Muenchian分组方法,先定义组合键再匹配唯一组:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:nsmpr1="http://xmlns.oracle.com/types"
    xmlns:ns20="http://TargetNamespace.com/fileReference"
    exclude-result-prefixes="nsmpr1 ns20">

    <xsl:output method="xml" indent="yes"/>

    <!-- 定义基于DOC和DOCO组合的键,用分隔符避免拼接冲突 -->
    <xsl:key name="afile-key" match="ns20:AFile" 
             use="concat(ns20:DOC, '|', ns20:DOCO)"/>

    <xsl:template match="/">
        <xsl:variable name="FileFromInprogress" select="."/>
        <!-- 只选择每组的第一个节点 -->
        <xsl:for-each select="$FileFromInprogress/nsmpr1:SyncFileResponse/ns20:AFiles/ns20:AFile[generate-id() = generate-id(key('afile-key', concat(ns20:DOC, '|', ns20:DOCO))[1])]">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

关键注意事项

  • 必须确保XSLT头部的命名空间前缀nsmpr1和ns20正确绑定到对应的URI,这是分组逻辑生效的核心前提。
  • 多键分组(方案1)更直观且无拼接冲突风险,优先使用;Muenchian分组是XSLT 1.0环境下的经典解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 09:34:52