为什么XQuery中的数值文本永远不能是xs:positiveInteger类型?
我注意到XQuery实现在处理(子)类型方面的细微差别。特别是,将文字数字作为输入处理到已声明接受输入类型的函数。 我天真地认为,任何可转换为特定数字类型的数字文字都会被接受为什么XQuery中的数值文本永远不能是xs:positiveInteger类型?,xquery,xquery-3.1,Xquery,Xquery 3.1,我注意到XQuery实现在处理(子)类型方面的细微差别。特别是,将文字数字作为输入处理到已声明接受输入类型的函数。 我天真地认为,任何可转换为特定数字类型的数字文字都会被接受 declare function local:any ($n as xs:anyAtomic) { $n }; declare function local:decimal ($n as xs:decimal) { $n }; declare function local:integer ($n as xs:integer
declare function local:any ($n as xs:anyAtomic) { $n };
declare function local:decimal ($n as xs:decimal) { $n };
declare function local:integer ($n as xs:integer) { $n };
declare function local:pos-int ($n as xs:positiveInteger) { $n };
local:any(1), (: works :)
local:decimal(1), (: works :)
local:integer(1), (: works :)
local:pos-int(1) (: throws in all tested implementations :)
exist db允许xs:long
,xs:int
。。。撒克逊人没有
我在Xquery规范中找不到这种行为的任何原因
nor Xpath函数规范
这里有人能解释一下为什么Saxon 9.3.1他、BaseX 9.3.1[独立]和eXist 5.3.0-SNAPSHOT会这样做吗
我是否错过了规范中定义将文本1
转换为xs:integer的部分?
xs:decimal作为最顶层的类型会更有意义,但是如果允许使用一个子类型,为什么不一直使用呢
您可以将数值文本
1
传递给MarkLogic中的local:pos-int()
函数:
declare function local:any($n as xs:anyAtomicType ) { $n };
declare function local:decimal($n as xs:decimal) { $n };
declare function local:integer($n as xs:integer) { $n };
declare function local:pos-int($n as xs:positiveInteger) { $n };
local:any(1), (: works :)
local:decimal(1), (: works :)
local:integer(1), (: works :)
local:pos-int(1) (: works fine in MarkLogic :)
您可以使用报告返回的值属于类型positiveInteger
xquery version "1.0-ml";
declare function local:pos-int($n as xs:positiveInteger) { $n };
xdmp:type(local:pos-int(1))
指定允许的促销类型:
数字类型升级:
xs:float类型的值(或通过限制从
xs:float)可以升级为xs:double类型。结果是
xs:与原始值相同的双精度值
xs:decimal类型的值(或通过限制从
xs:decimal)可以升级为xs:float或
xs:双倍。此促销的结果是通过铸造
将原始值转换为所需类型。这种促销可能会导致
精度损失
对于其他类型,您必须显式地使用构造函数,例如
local:int(xs:int(1))
我认为这方面的规范是非常不幸的,但很明显:值只有在标记为这样的情况下才是xs:positiveInteger
,而不仅仅是因为它是(a)整数和(b)正数。XQuery工作组对此进行了长时间的讨论,涉及到编程语言类型系统方面的一些著名专家(如Phil Wadler),这就是我们做出的决定。我自己也不喜欢
说明书上怎么说的?XDM规范中的定义是一个良好的开端:
[定义:原子值是一个元素的值空间中的值
原子类型,并标有该原子类型的名称。]
[定义:原子类型是基元简单类型或
通过限制从另一个原子类型派生。](通过
列表或联合不是原子的。)
[定义:基本简单类型是2.1.1中定义的类型
从XML架构中采用的类型。]
XQuery规范中的§3.1.1谈到了数字文字:
不包含“.”且不包含e或e的数值文字的值
字符是xs:integer类型的原子值
§3.18.1给出了运营商“实例”的规则:
如果其值为
第一个操作数与其第二个操作数中的SequenceType匹配,
根据SequenceType匹配规则
§2.5.5.2给出了SequenceType匹配的相关规则:
仅由EQName组成的ItemType被解释为
原子型。预期的类型AtomicOrUnionType与
实际类型为AT的原子值,如果从(AT,
AtomicOrUnionType)是真的
综上所述,其结果是xs:positiveInteger的表达式3实例返回false(因为xs:integer
不是从xs:positiveInteger
派生的)
最后,当函数参数的预期类型为xs:positiveInteger
,且函数调用提供值3时,§3.1.5.2中的函数转换规则起作用。它们允许从提供的值到所需类型的各种转换,但从xs:integer到xs:positiveInteger的“下转换”不在其中。所以这是一个错误:
如果在上述转换之后,结果值不匹配
根据SequenceType匹配规则的预期类型
引发类型错误[err:XPTY0004]
正如我所说,我不喜欢这些规则,并且在许多场合试图改变它们。但是它们是明确的,任何不遵循它们的产品都是不一致的。示例代码中的语法有点不一致。与其说是declare local:any function(…
,不如说是declare function local:any(…
)。我为exist打开了一个问题,谢谢你详尽的回答。我很确定,我错过了规范。从@Micheal Kay和@Martin Honnen给出的答案来看,这似乎不符合规范(正如exist db允许对xs:long
及其子类型进行向下转换的行为一样)。令人感兴趣的是,这些产品是否允许将十进制值1.3传递给期望xs:integer的函数?我之所以这样问,是因为与纯“向下转换”不同,向下转换允许这样做它只检查值的一致性,不进行任何转换。当使用值1.3
执行时,会引发以下强制错误:[1.0-ml]XDMP-AS:(err:XPTY0004)$n AS xs:positiveInteger--无效强制:1.3 AS xs:positiveInteger