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

XSLT 2.0带计数器按模板循环处理数据异常问题及实现方法

异常产生原因

该异常完全由XSLT 1.0与XSLT 2.0的类型系统、运算规则差异导致,原代码依赖XSLT 1.0的隐式类型转换逻辑,在2.0环境下完全失效:

  • 原代码所有xsl:param未声明类型,传参时未使用select属性直接传值,而是在xsl:with-param内嵌xsl:value-of构造内容。XSLT 1.0中该方式传递的是结果树片段(RTF),执行<=比较时处理器会自动将RTF转为数值类型对比,逻辑符合预期。
  • XSLT 2.0基于强类型的XPath 2.0数据模型,上述写法传递的是临时文档节点,无显式类型声明时,<=运算符对两个无类型操作数会默认按字符串字典序比较,而非数值比较:
    • count为1-8的个位数时,i和count的字符串形式均为单字符,字典序与数值序完全一致,运行结果正常。
    • count=9时,所有1-8开头的多位数(10~89)字符串首字符编码均小于9,比较结果恒为真,直到i增长到90时,字符串"90"字典序大于"9"才会停止递归,最终执行约90次,与观测现象一致。
    • count≥10时,count字符串首字符为1,i=2对应的字符串"2"首字符编码大于1,第一次递归后判断即不成立,仅执行1次;count≥20时首字符为2,i=3时比较不成立,仅执行2次,执行次数随count首位字符变化无规律。
XSLT 2.0 正确实现方案

XSLT 2.0原生支持整数序列遍历,无需手写递归实现固定次数循环,代码更简洁可靠;如果需要保留原有递归结构,必须显式声明参数类型,避免隐式转换错误。

推荐方案:序列遍历实现(无递归)

直接使用xsl:for-each遍历1到目标次数的整数序列,完全规避递归栈溢出、隐式类型转换问题:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                version="2.0">
  <xsl:template match="/">
    <Klammer>
      <!-- 遍历1到13的整数序列,修改13即可调整循环次数 -->
      <xsl:for-each select="1 to 13">
        <xsl:call-template name="myRepeatedTemplate">
          <!-- 当前上下文项即为循环计数器值,直接传整数类型参数 -->
          <xsl:with-param name="number" select="." as="xs:integer"/>
        </xsl:call-template>
      </xsl:for-each>
    </Klammer>
  </xsl:template>

  <xsl:template name="myRepeatedTemplate">
    <xsl:param name="number" as="xs:integer"/>
    <Testelement>
      <Testnumber>
        <xsl:value-of select="$number"/>
      </Testnumber>
    </Testelement>
  </xsl:template>
</xsl:stylesheet>

递归逻辑修正方案

如果必须保留原有递归调用结构,需要给所有参数显式声明整数类型,传参时使用select直接传递数值表达式,禁止构造临时树节点:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                version="2.0">
  <xsl:template match="/">
    <Klammer>
      <xsl:call-template name="selects">
        <xsl:with-param name="i" select="1" as="xs:integer"/>
        <xsl:with-param name="count" select="13" as="xs:integer"/>
      </xsl:call-template>
    </Klammer>
  </xsl:template>

  <xsl:template name="selects">
    <!-- 显式声明参数为整数类型,强制走数值比较逻辑 -->
    <xsl:param name="i" as="xs:integer"/>
    <xsl:param name="count" as="xs:integer"/>
    <xsl:if test="$i <= $count">
      <xsl:call-template name="myRepeatedTemplate">
        <xsl:with-param name="number" select="$i" as="xs:integer"/>
      </xsl:call-template>
      <!-- 直接传递数值计算结果,不嵌套xsl:value-of构造临时节点 -->
      <xsl:call-template name="selects">
        <xsl:with-param name="i" select="$i + 1" as="xs:integer"/>
        <xsl:with-param name="count" select="$count" as="xs:integer"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

  <xsl:template name="myRepeatedTemplate">
    <xsl:param name="number" as="xs:integer"/>
    <Testelement>
      <Testnumber>
        <xsl:value-of select="$number"/>
      </Testnumber>
    </Testelement>
  </xsl:template>
</xsl:stylesheet>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:27:13