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

如何用XSLT 2/3选择版本≤输入值且最接近的topic节点?

问题描述

我有一个包含多个带version属性的topic节点的XML,版本为数值型。存在相同id、不同版本的topic节点。需要选择其中一个topic节点:版本小于等于输入变量且最接近该变量的节点。

示例XML:

<topics>
  <topic id="1" version="6"/>
  <topic id="1" version="3"/>
  <topic id="1" version="1"/>
</topics>

匹配规则:

  • 输入变量为7时,选择version="6"的topic;
  • 输入为6时选version="6"的;
  • 输入为5时选version="3"的。

目前通过枚举版本的xsl:choose实现,但版本已有16个且后续会增加,希望替换该枚举方案(使用Saxon,支持XSLT 2和3)。

当前枚举实现代码:

<xsl:variable name="ver" select="7"/>
<xsl:choose>
    <xsl:when test="//topic[@version = $ver]">
        <xsl:copy-of select="//topic[@version = $ver]">
    </xsl:when>
    <xsl:when test="//topic[@version = $ver -1]">
        <xsl:copy-of select="//topic[@version = $ver -1]">
    </xsl:when>
    ...
</xsl:choose>
解决方案

XSLT 2.0 通用实现

无需枚举版本,通过过滤+排序直接定位目标节点:

<xsl:variable name="target-ver" select="7"/>
<!-- 筛选当前id下版本≤目标值的节点,按版本降序排序后取第一个 -->
<xsl:copy-of select="
    (//topic[@id='1']
        [number(@version) <= $target-ver]
        order by number(@version) descending
    )[1]
"/>

XSLT 3.0 简洁实现

借助max()函数直接获取符合条件的最大版本,再匹配对应节点:

<xsl:variable name="target-ver" select="7"/>
<xsl:variable name="max-valid-ver" select="
    max(//topic[@id='1']/number(@version)[. <= $target-ver])
"/>
<xsl:copy-of select="//topic[@id='1' and @version = $max-valid-ver]"/>

如果需要批量处理多个不同id的分组场景,XSLT 3.0的分组语法更高效:

<xsl:variable name="target-ver" select="7"/>
<xsl:for-each-group select="//topic" group-by="@id">
    <xsl:variable name="max-ver" select="max(current-group()/number(@version)[. <= $target-ver])"/>
    <xsl:copy-of select="current-group()[@version = $max-ver]"/>
</xsl:for-each-group>

关键说明

  • 用number()转换version属性为数值,避免字符串排序的错误(比如"10"字符串排序会排在"2"前面);
  • 核心逻辑统一为:先过滤版本≤目标值的节点,再从中选版本最大的,彻底摆脱枚举依赖;
  • Saxon对上述XSLT 2/3语法完全支持,无需额外配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 06:05:09