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

如何在XSLT中优雅处理空group-by表达式

XSLT分组时保留空序列分组的解决方案

给定这段XSLT代码:

<xsl:variable name="sequence" select="
              ( map { 'foo' : 1, 'bar' : () },
                map { 'foo' : 1, 'bar' : () },
                map { 'foo' : 1, 'bar' : '3' } )" as="map(xs:string,item()*)*"/>
<xsl:variable name="distinct" as="map(xs:string,item()*)*">
    <xsl:for-each-group select="$sequence" group-by="map:get(.,'bar')">
        <xsl:sequence select="map { 'group' : current-grouping-key() }"/>            
    </xsl:for-each-group>
</xsl:variable>

期望得到包含空序列分组的结果:

( map { 'group' : () }
  map { 'group' : 3  } )

但实际运行后只得到非空键的分组:

( map { 'group' : 3  } )

问题根源

XSLT的for-each-group在处理group-by时,会自动排除分组键为空序列()的节点——这类节点不会被分到任何组里,直接被忽略。

优雅解决方案

方案1:用唯一标识替换空序列分组键

给空序列的分组键设置一个不会和业务值冲突的唯一标识(比如自定义QName),分组后再转换回空序列:

<xsl:variable name="sequence" select="
              ( map { 'foo' : 1, 'bar' : () },
                map { 'foo' : 1, 'bar' : () },
                map { 'foo' : 1, 'bar' : '3' } )" as="map(xs:string,item()*)*"/>
<xsl:variable name="distinct" as="map(xs:string,item()*)*">
    <xsl:for-each-group select="$sequence" 
                        group-by="if (exists(map:get(., 'bar'))) 
                                  then map:get(., 'bar') 
                                  else xs:QName('empty-group')">
        <xsl:sequence select="
            map { 
                'group' : if (current-grouping-key() instance of xs:QName) 
                          then () 
                          else current-grouping-key() 
            }"/>            
    </xsl:for-each-group>
</xsl:variable>

方案2:用数组包裹分组键(XPath 3.1+)

利用数组即使包含空序列也属于非空值的特性,把bar的值包裹成数组作为分组键,之后再提取数组元素还原原值:

<xsl:variable name="distinct" as="map(xs:string,item()*)*">
    <xsl:for-each-group select="$sequence" 
                        group-by="array{map:get(., 'bar')}">
        <xsl:sequence select="
            map { 
                'group' : current-grouping-key()?1 
            }"/>            
    </xsl:for-each-group>
</xsl:variable>

这个方案更简洁,不需要额外的判断逻辑,适合支持XPath 3.1及以上的处理器。

内容的提问来源于stack exchange,提问作者MrD at KookerellaLtd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 20:40:22