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

如何在XSLT中对含字母数字混合的属性'd'进行排序?

XSLT实现混合格式属性'd'的数字优先升序排序

问题背景

需对一组文档按属性d升序排序,属性值为字母与数字混合的层级格式(示例:11A-1-000003、11-1-000008a)。核心排序规则为数字优先:数字代表主章节,字母代表子章节,层级间按-分割,需先比较每个层级的数字部分(数值大小),再比较字母部分(文本顺序)。

此前尝试的4种方案均未达标:

  • 纯文本排序:会出现11-24-00043a排在11-3-000023前的问题(文本比较中2的ASCII码小于3)
  • 提取纯数字排序:丢失字母信息,无法区分11-1与11-1C
  • 多层substring分割:灵活性差,无法适配不同层级长度或字母位置不固定的场景
  • 简单tokenize后排序:未拆分层级内的数字与字母,导致11-1C-000008排在11-15B-000008后的错误结果

预期排序示例:
11-1-000008a → 11-1C-000008 → 11-3-000023 → 11-3-000023a → 11-3-000023b → 11-9-000002 → 11-15-00014 → 11-15B-00014a → 11-16-000009 → 11-24-00043a → 11A-1-000003 → 12-1-000008a → 13-1-000007a

解决方案(XSLT 2.0+)

利用tokenize拆分层级、自定义函数拆分每个层级的数字与字母,实现多维度排序:

完整代码示例

<!-- 自定义函数:拆分单个层级段为数字+字母 -->
<xsl:function name="local:split-segment" as="item()*">
  <xsl:param name="segment" as="xs:string"/>
  <xsl:analyze-string select="$segment" regex="^(\d*)(.*)$">
    <xsl:matching-substring>
      <!-- 数字部分转为整数,无数字则返回0 -->
      <xsl:sequence select="if (regex-group(1) ne '') then xs:integer(regex-group(1)) else 0"/>
      <!-- 保留字母部分(含空字符串) -->
      <xsl:sequence select="regex-group(2)"/>
    </xsl:matching-substring>
  </xsl:analyze-string>
</xsl:function>

<!-- 排序模板 -->
<xsl:template match="root">
  <xsl:copy>
    <xsl:for-each select="document">
      <!-- 按层级拆分后,依次比较每个层级的数字、字母 -->
      <xsl:sort select="tokenize(@d, '-') ! local:split-segment(.)" 
                data-type="text" 
                order="ascending"/>
      <xsl:copy-of select="."/>
    </xsl:for-each>
  </xsl:copy>
</xsl:template>

工作原理

  1. 层级拆分:通过tokenize(@d, '-')将属性值按-拆分为多个层级段(如11A-1-000003拆分为['11A', '1', '000003'])
  2. 段内拆分:local:split-segment函数将每个层级段拆分为「数字部分(整数类型)」和「字母部分(文本类型)」,例如:
    • 11A → 11 + A
    • 15B → 15 + B
    • 000003 → 3 + ``(空字符串)
  3. 多维度排序:排序时按层级顺序依次比较:
    • 先比较当前层级的数字部分(数值大小),数字小的条目排前
    • 数字部分相同则比较字母部分(文本顺序),字母靠前的排前
    • 当前层级完全相同则比较下一层级,以此类推

注意事项

  • 需使用支持XSLT 2.0或更高版本的处理器(如Saxon),依赖tokenize、analyze-string及自定义函数特性
  • 若层级段无数字(如A-1-000001),数字部分默认返回0,确保此类条目排在数字开头的条目之前
  • 字母部分排序遵循默认文本规则,如需区分大小写可添加case-order="upper-first"或lower-first参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 02:23:15