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

XQuery递归应用异常:表达式计算结果为0的排查求助

XQuery表达式计算函数结果异常排查

我编写了以下XQuery函数用于计算表达式值:

declare function local:calculateExpression($expression) as xs:decimal {
    let $result :=
        if ($expression/uli:times) then
            fold-left($expression/uli:times/*/@value, 1, 
                function($acc, $val) { $acc * ($val) })
        else if ($expression/uli:plus) then
          sum( for $child in $expression/uli:plus/@value
            return local:calculateExpression($child))
        else if ($expression/uli:minus) then
            local:calculateMinus($expression/uli:minus)
        else if ($expression/uli:int) then
            xs:decimal($expression/uli:int/@value)
        else if ($expression/uli:dec) then
            xs:decimal($expression/uli:dec/@value)
        else if ($expression instance of xs:decimal) then
            xs:decimal($expression/uli:int/@value)

        else
            0 (: Default value if no recognized operation is found :)
    return
        if (empty($result)) then 0 else $result
};

declare function local:calculateMinus($minus as element()) as xs:decimal {
    let $operands := $minus/*
    return 
        if (count($operands) = 2) then
            local:calculateExpression($operands[1]) - local:calculateExpression($operands[2])
        else
            local:calculateExpression($operands[1]) - sum(for $op in $operands[position() > 1] return local:calculateExpression($op))
};

但处理以下场景时,计算结果始终为0:

<answer-debug>
    <questionID QuestionID="Q4"></questionID>
    <answerValue>Not Answered</answerValue>
    <correctValue>0</correctValue>
    <answerType>string</answerType>
    <correctValueType>decimal</correctValueType>
    <comparisonResult>Not Answered</comparisonResult>
    <marks>0</marks>
</answer-debug>

参考的问题XML结构如下:

<Question id="Q4" level="1">
    <Expression>
        <description/>
        <plus>
            <int value="1"/>
            <int value="1"/>
        </plus>
    </Expression>
    <Feedback answerCorrect="t">Well done!</Feedback>
    <Feedback answerCorrect="f">Please pay more attention next time.</Feedback>
</Question>

问题分析与修正

函数存在以下几个关键问题:

  • 命名空间不匹配
    函数中使用了uli:命名空间前缀,但参考XML里的<plus>、<int>等元素并没有该前缀,导致所有带uli:的元素选择器无法匹配目标节点,直接走到else分支返回0。

  • Plus分支逻辑错误
    原代码中plus分支遍历的是$expression/uli:plus/@value,但参考XML里的<plus>是通过子元素承载操作数,而非自身的value属性。正确逻辑应遍历<plus>的子元素。

  • xs:decimal类型分支逻辑错误
    当$expression本身是xs:decimal类型时,原代码尝试获取$expression/uli:int/@value完全不符合逻辑,应直接返回$expression本身。

  • 类型转换遗漏
    times分支中$val是属性节点,未显式转换为xs:decimal,可能引发类型错误。


修正后的函数代码

declare function local:calculateExpression($expression) as xs:decimal {
    let $result :=
        if ($expression/times) then
            fold-left($expression/times/*/@value, 1, 
                function($acc, $val) { $acc * xs:decimal($val) })
        else if ($expression/plus) then
            sum(for $child in $expression/plus/* return local:calculateExpression($child))
        else if ($expression/minus) then
            local:calculateMinus($expression/minus)
        else if ($expression/int) then
            xs:decimal($expression/int/@value)
        else if ($expression/dec) then
            xs:decimal($expression/dec/@value)
        else if ($expression instance of xs:decimal) then
            $expression
        else
            0 (: Default value if no recognized operation is found :)
    return
        if (empty($result)) then 0 else $result
};

declare function local:calculateMinus($minus as element()) as xs:decimal {
    let $operands := $minus/*
    return 
        if (count($operands) = 2) then
            local:calculateExpression($operands[1]) - local:calculateExpression($operands[2])
        else
            local:calculateExpression($operands[1]) - sum(for $op in $operands[position() > 1] return local:calculateExpression($op))
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:23:18