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

如何在单个XSLT样式表中执行多步顺序转换

解决XSLT合并后排序未使用修改后节点值的问题

问题出在合并后的样式表中,排序操作直接读取了原始XML的f2节点值,而非第一步修改后的结果。以下是两种可行的解决思路:

方案一:先生成修改后的节点集,再排序

先通过变量保存所有c节点修改后的结果,再对这个变量中的节点执行排序操作。这种方式适合XSLT 1.0及以上版本(XSLT 1.0需要用节点集函数将结果树片段转为可操作的节点集):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt">
  <!-- 默认身份转换模板,复制未匹配的节点 -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- 处理<root/s/a/b>节点:先修改子节点,再排序 -->
  <xsl:template match="root/s/a/b">
    <xsl:copy>
      <!-- 第一步:生成所有修改f2后的<c>节点,存入变量 -->
      <xsl:variable name="modified-c-nodes">
        <xsl:apply-templates select="c"/>
      </xsl:variable>
      <!-- 第二步:对修改后的节点按f1、修改后的f2排序 -->
      <xsl:for-each select="msxsl:node-set($modified-c-nodes)/c">
        <xsl:sort select="f1"/>
        <xsl:sort select="f2"/>
        <xsl:copy-of select="."/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

  <!-- 修改f2节点:末尾带'x'的添加前缀'0' -->
  <xsl:template match="c/f2[substring(., string-length(.)) = 'x']">
    <f2>0<xsl:value-of select="."/></f2>
  </xsl:template>
</xsl:stylesheet>

如果使用XSLT 2.0或更高版本,无需msxsl:node-set,直接用$modified-c-nodes/c即可访问变量中的节点。

方案二:排序时直接计算修改后的f2值

无需提前生成修改后的节点集,在排序逻辑中直接计算f2的修改后值,确保排序依据的是最终要输出的内容:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- 默认身份转换模板 -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- 处理<root/s/a/b>节点:先排序(用修改后的f2值),再应用修改模板 -->
  <xsl:template match="root/s/a/b">
    <xsl:copy>
      <xsl:for-each select="c">
        <xsl:sort select="f1"/>
        <!-- 排序时直接计算带前缀的f2值 -->
        <xsl:sort select="if (substring(f2, string-length(f2)) = 'x') then concat('0', f2) else f2"/>
        <!-- 对排序后的节点应用修改模板,输出最终结果 -->
        <xsl:apply-templates select="."/>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

  <!-- 修改f2节点的模板 -->
  <xsl:template match="c/f2[substring(., string-length(.)) = 'x']">
    <f2>0<xsl:value-of select="."/></f2>
  </xsl:template>
</xsl:stylesheet>

关键说明

之前合并失败的原因是排序操作优先基于原始节点值执行,之后才应用修改模板。上述两种方案都确保了排序依据的是修改后的f2值:方案一是先完成修改再排序,方案二是在排序时直接使用修改后的计算逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 01:17:37