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

使用xsl:try/xsl:catch时,捕获10次错误后如何终止XSLT转换?

问题描述

我们使用Saxon 12.6进行突发流式XSLT转换,处理包含多个独立<Dok>节点的XML文件。目前通过<xsl:try>/<xsl:catch>实现了单个<Dok>转换的动态错误不影响其他节点的逻辑,但希望当捕获的错误超过10次时,终止转换并重新抛出错误,找不到简单的错误计数方式。

已考虑的方案:

  • 使用Java扩展函数实现计数器,但过于复杂
  • 使用<xsl:accumulator>,但未成功实现

XML文件结构示例

<Export>
    <Dok>
       <more_than_1000_lines_of_XML_to_be_transformed/>
    </Dok>
    <Dok>
       <more_than_1000_lines_of_XML_to_be_transformed/>
    </Dok>
    <Dok>
       <more_than_1000_lines_of_XML_to_be_transformed/>
    </Dok>
    <!-- typically 250 to 1000 of such <Dok> -->
</Export>        

简化后的XSLT代码

<xsl:template match="Export" mode="streamedDefaultMode">
   <xsl:apply-template select="snapshot(Dok)" mode="grounded"/>
</xsl:template>

<xsl:template match="Dok" mode="grounded" priority="99">
   <xsl:try>
      <xsl:next-match/>
      <xsl:catch errors="*">

          <!-- here I would like something like:   if ($numberOfCaughtErrors > 10) then throw "fatal error and abort the transformation -->

          <xsl:variable name="logMsg" select="string-join(('TrafoTransformErrorStufeCC: ', $xslerr:code, $xslerr:description,' in ', $xslerr:module, ' on  line: ', $xslerr:line-number,' value: ', $xslerr:value ),' ')"/>

          <xsl:message select="$logMsg"/>
          <Dok status="error">
             <Msg><xsl:value-of select="$logMsg"/></Msg>
          </Dok>
    </xsl:catch>
</xsl:template>

<xsl:template match="Dok" mode="grounded">
   <!-- do the real transformation of a Dok -> 1000s of lines of XSLT code -->
</xsl:template>

简便解决方案

方案1:修复<xsl:accumulator>实现

<xsl:accumulator>完全适配流式场景,之前未成功可能是配置细节问题,以下是正确实现方式:

  1. 定义全局累加器
    在样式表顶部添加累加器,用于计数错误次数:

    <xsl:accumulator name="error-count" initial-value="0" streamable="yes">
        <!-- 默认不修改计数 -->
        <xsl:accumulator-rule match="Dok" phase="end" select="$value"/>
        <!-- 仅在捕获到错误时,计数+1 -->
        <xsl:accumulator-rule match="Dok" mode="grounded" select="$value + 1" condition="$xslerr:code"/>
    </xsl:accumulator>
    
  2. 在<xsl:catch>中检查计数并终止
    修改<xsl:catch>逻辑,当计数超过10时抛出致命错误:

    <xsl:catch errors="*">
        <xsl:variable name="current-error-count" select="accumulator-before('error-count') + 1"/>
        <xsl:if test="$current-error-count > 10">
            <!-- 直接终止转换 -->
            <xsl:message terminate="yes">Fatal error: Exceeded maximum allowed errors (10)</xsl:message>
            <!-- 或抛出结构化错误 -->
            <xsl:throw code="custom:too-many-errors" description="Exceeded 10 transformation errors"/>
        </xsl:if>
    
        <!-- 原错误日志和输出逻辑 -->
        <xsl:variable name="logMsg" select="string-join(('TrafoTransformErrorStufeCC: ', $xslerr:code, $xslerr:description,' in ', $xslerr:module, ' on  line: ', $xslerr:line-number,' value: ', $xslerr:value ),' ')"/>
        <xsl:message select="$logMsg"/>
        <Dok status="error">
            <Msg><xsl:value-of select="$logMsg"/></Msg>
        </Dok>
    </xsl:catch>
    
  3. 启用累加器
    在流式模式声明中指定使用累加器:

    <xsl:mode name="streamedDefaultMode" streamable="yes" use-accumulators="#all"/>
    

方案2:使用<xsl:iterate>维护计数

如果累加器仍有问题,可改用<xsl:iterate>遍历节点,直接维护可变计数变量(XSLT 3.0支持迭代中更新参数):

<xsl:template match="Export" mode="streamedDefaultMode">
   <xsl:iterate select="snapshot(Dok)">
       <xsl:param name="error-count" select="0"/>
       <xsl:try>
           <xsl:apply-templates select="." mode="grounded"/>
           <!-- 无错误时保持计数不变 -->
           <xsl:next-iteration>
               <xsl:with-param name="error-count" select="$error-count"/>
           </xsl:next-iteration>
       </xsl:try>
       <xsl:catch errors="*">
           <xsl:variable name="new-error-count" select="$error-count + 1"/>
           <xsl:if test="$new-error-count > 10">
               <xsl:throw code="custom:too-many-errors" description="Exceeded 10 transformation errors"/>
           </xsl:if>

           <!-- 原错误日志和输出逻辑 -->
           <xsl:variable name="logMsg" select="string-join(('TrafoTransformErrorStufeCC: ', $xslerr:code, $xslerr:description,' in ', $xslerr:module, ' on  line: ', $xslerr:line-number,' value: ', $xslerr:value ),' ')"/>
           <xsl:message select="$logMsg"/>
           <Dok status="error">
               <Msg><xsl:value-of select="$logMsg"/></Msg>
           </Dok>

           <!-- 更新计数后继续迭代 -->
           <xsl:next-iteration>
               <xsl:with-param name="error-count" select="$new-error-count"/>
           </xsl:next-iteration>
       </xsl:catch>
   </xsl:iterate>
</xsl:template>

该方案逻辑更直观,无需依赖累加器配置,同样适配流式场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 06:14:52