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

如何用XSLT 1.0对节点stations属性的字符串列表排序?

在XSLT 1.0(xsltproc)中实现stations属性值排序

可以实现,以下是针对两种排序需求的具体解决方案——因为XSLT 1.0没有内置字符串拆分函数,我们需要通过递归模板拆分stations属性的空格分隔值,排序后再重新拼接。


方案1:按索引数值升序排序

针对你给出的数值排序示例(/1/@stations.2 → /1/@stations.4 → ... → /1/@stations.26),需要提取每个条目末尾的数字,转换为数值后排序。

完整XSLT代码

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common">
  <!-- 默认复制模板:原样复制所有未被特殊匹配的节点/属性 -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- 匹配constraint节点的stations属性,替换为排序后的字符串 -->
  <xsl:template match="@stations">
    <xsl:attribute name="stations">
      <xsl:call-template name="split-and-sort">
        <xsl:with-param name="input" select="."/>
        <xsl:with-param name="sort-type" select="'numeric'"/>
      </xsl:call-template>
    </xsl:attribute>
  </xsl:template>

  <!-- 递归拆分+排序+拼接的核心模板 -->
  <xsl:template name="split-and-sort">
    <xsl:param name="input"/>
    <xsl:param name="sort-type" select="'text'"/>
    <xsl:param name="delimiter" select="' '"/>
    
    <!-- 拆分字符串为临时节点集 -->
    <xsl:variable name="entries">
      <xsl:call-template name="split-string">
        <xsl:with-param name="string" select="$input"/>
        <xsl:with-param name="delimiter" select="$delimiter"/>
      </xsl:call-template>
    </xsl:variable>

    <!-- 排序并拼接 -->
    <xsl:for-each select="exsl:node-set($entries)/entry">
      <xsl:choose>
        <xsl:when test="$sort-type = 'numeric'">
          <!-- 按末尾数字的数值升序排序 -->
          <xsl:sort select="number(substring-after(., '.'))" data-type="number" order="ascending"/>
        </xsl:when>
        <xsl:otherwise>
          <!-- 默认按字母升序排序 -->
          <xsl:sort select="." data-type="text" order="ascending"/>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:value-of select="."/>
      <!-- 非最后一个条目添加空格分隔符 -->
      <xsl:if test="position() != last()">
        <xsl:text> </xsl:text>
      </xsl:if>
    </xsl:for-each>
  </xsl:template>

  <!-- 递归拆分字符串为单个entry节点 -->
  <xsl:template name="split-string">
    <xsl:param name="string"/>
    <xsl:param name="delimiter"/>
    <xsl:variable name="first" select="substring-before($string, $delimiter)"/>
    <xsl:variable name="rest" select="substring-after($string, $delimiter)"/>
    
    <xsl:choose>
      <xsl:when test="$first != ''">
        <entry><xsl:value-of select="$first"/></entry>
        <xsl:call-template name="split-string">
          <xsl:with-param name="string" select="$rest"/>
          <xsl:with-param name="delimiter" select="$delimiter"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$string != ''">
        <entry><xsl:value-of select="$string"/></entry>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

方案2:按字母升序排序

如果需要你给出的字母排序结果(/1/@stations.11 → /1/@stations.12 → /1/@stations.2 → ...),只需修改调用模板时的sort-type参数。

快速调整方式

将match="@stations"模板中的sort-type参数改为'text':

<xsl:call-template name="split-and-sort">
  <xsl:with-param name="input" select="."/>
  <xsl:with-param name="sort-type" select="'text'"/>
</xsl:call-template>

使用方法(Linux xsltproc)

将上述XSLT保存为sort-stations.xsl,输入XML保存为input.xml,执行以下命令:

xsltproc sort-stations.xsl input.xml > output.xml

关键注意事项

  1. node-set扩展:代码中使用的exsl:node-set是libxslt(xsltproc底层库)原生支持的扩展函数,无需额外配置即可使用。
  2. 数值排序准确性:通过number(substring-after(., '.'))提取条目末尾的数字,确保排序是按数值大小而非字符串顺序,避免11排在2前面的问题。
  3. 兼容性:所有代码严格遵循XSLT 1.0规范,完全兼容xsltproc。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 16:54:55