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
相关产品推荐
相关产品推荐

