Saxon HE 9.7中xs:integer传变量编译报错,变量实为有效整数字符串
问题描述
使用Saxon SAXON-HE 9.7.0.15J执行以下XQuery脚本:
let $i := $input//*:i let $code := substring($i,4,4) let $n := xs:integer($code) return $n
其中$input对应的XML为:
<req> <i>1234004</i> </req>
编译时出现错误**"Cannot convert zero-length string to an integer"**,但预期运行时$code应为"4004"。使用castable判断或number()函数的脚本可正常执行,疑问为何无法将变量传入xs:integer()。
原因分析
Saxon HE 9.7在编译阶段会执行静态类型检查:
$input//*:i返回的是元素节点序列,编译器无法在编译阶段确定该序列一定非空(比如XML中不存在<i>节点的情况)。- 当
$i为空序列时,substring($i,4,4)会返回空字符串,而xs:integer()不允许传入空字符串作为参数。 - 编译器预判到这种潜在错误场景,因此提前抛出编译错误。
而number()函数对空字符串会返回NaN,不会触发编译级别的限制;castable判断是在运行时进行类型校验,也不会在编译阶段报错。
解决方法
可以通过以下几种方式解决这个问题:
- 明确获取非空文本节点:将
$i的定义改为获取单个文本节点,确保静态分析时确定其非空(假设XML结构固定):let $i := $input//*:i/text()[1] let $code := substring($i,4,4) let $n := xs:integer($code) return $n - 添加运行时类型检查:用
castable判断确保转换安全:let $i := $input//*:i let $code := substring($i,4,4) let $n := if ($code castable as xs:integer) then xs:integer($code) else () return $n - 使用
number()函数替代:注意number()对非数字字符串会返回NaN,需后续处理:let $i := $input//*:i let $code := substring($i,4,4) let $n := number($code) return $n - 添加节点存在性检查:先确保
$i非空再执行转换:let $i := $input//*:i let $n := if (exists($i)) then xs:integer(substring($i,4,4)) else () return $n
内容的提问来源于stack exchange,提问作者Vladimir Dyuzhev
相关产品推荐
相关产品推荐

