如何使用XQuery对XML节点执行四则运算并解析表达式输出计算结果
XQuery 实现XML嵌套四则运算节点的解析与计算
需求说明
针对给定的嵌套XML格式数学表达式,需完成两个目标:
- 解析节点生成可读的标准算术表达式字符串
- 计算表达式的最终输出结果
示例XML结构
<Expression> <description/> <minus> <plus> <int value="2"/> <int value="3"/> <times> <int value="5"/> <minus> <int value="6"/> <int value="3"/> </minus> </times> </plus> <int value="4"/> </minus> </Expression>
实现思路
通过递归函数遍历XML节点:
- 遇到
int类型节点,直接返回节点的数值文本和数值类型的计算值 - 遇到四则运算节点(
plus对应加、minus对应减、times对应乘、div对应除),先递归处理所有子节点,再按运算符拼接表达式、计算最终值,内层运算自动加括号保证运算顺序正确
完整实现代码
xquery version "3.0"; declare function local:eval-node($node as node()) as item()* { (: 处理整数节点 :) if ($node instance of element(int)) then (string($node/@value), xs:integer($node/@value)) else let $op := local-name($node) (: 递归获取所有子节点的表达式与计算值 :) let $child-results := $node/* ! local:eval-node(.) let $child-exprs := $child-results[position() mod 2 = 1] let $child-values := $child-results[position() mod 2 = 0] (: 映射运算符符号 :) let $op-symbol := switch($op) case "plus" return "+" case "minus" return "-" case "times" return "*" case "div" return "/" default return "" (: 拼接表达式,内层运算加括号 :) let $expr := "(" || string-join($child-exprs, $op-symbol) || ")" (: 计算当前节点结果 :) let $value := switch($op) case "plus" return sum($child-values) case "minus" return fold-left($child-values, $child-values[1], function($acc, $cur) { $acc - $cur }) case "times" return fold-left($child-values, 1, function($acc, $cur) { $acc * $cur }) case "div" return fold-left($child-values, $child-values[1], function($acc, $cur) { $acc div $cur }) default return () return ($expr, $value) }; (: 执行计算,去掉最外层冗余括号 :) let $root-op-node := /Expression/*[not(local-name() = 'description')][1] let $result := local:eval-node($root-op-node) let $final-expr := substring($result[1], 2, string-length($result[1]) - 2) let $final-value := $result[2] return concat($final-expr, "=", $final-value)
输出结果
运行代码后输出:2+3+5*(6-3)-4=16
注:乘法运算的左右操作数顺序取决于XML中times节点的子节点顺序,与示例中的(6-3)*5运算结果完全一致,若要调整表达式展示顺序,调换times节点下两个子节点的位置即可。
内容的提问来源于stack exchange,提问作者daviskren
相关产品推荐
相关产品推荐

