我注意到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) { $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 :)
existdb允许xs:long
、xs:int
。。。萨克森没有。
我在Xquery Spec 2.5.5 SequenceType Matching中找不到这种行为的任何原因也没有Xpath函数规范1.6.3原子类型层次
这里有人能解释为什么Saxon 9.3.1 HE、BaseX 9.3.1[Standalone]和eXist 5.3.0-SNAPSHOT会这样做吗?
我是不是错过了规范中定义将文字1
强制转换为xs:integer的部分?xs:decimal作为最顶层的类型会更有意义,但如果允许一个子类型,为什么不一直使用呢?
这是的现场演示
我认为这方面的规范非常不幸,但很明显:只有当一个值被标记为xs:positiveInteger
时,它才是CCD_4,而不仅仅是因为它是(a(整数和(b(正。XQuery工作组对此进行了长时间的讨论,一些著名的编程语言类型系统专家(如Phil Wadler(也参与了讨论,这就是我们做出的决定。我自己也不喜欢。
说明书上怎么写的?XDM规范中的定义是一个良好的开端:
https://www.w3.org/TR/xpath-datamodel-31/#xs-类型
[定义:原子值是原子类型,并用该原子类型的名称进行标记。]
[定义:原子类型是基元简单类型或类型通过限制从另一种原子类型派生。](类型派生自列表或并集不是原子。(
[定义:基元简单类型是2.1.1中定义的类型从XML架构中采用的类型。]
然后XQuery规范中的§3.1.1讨论了数字文本:
不包含"."和e或e的数字文本的值character是xs:integer类型的原子值。
§3.18.1给出了"实例"运算符的规则:
如果第一个操作数与其第二个操作数中的SequenceType匹配,根据SequenceType匹配规则;
和§2.5.5.2给出了SequenceType匹配的相关规则:
仅由EQName组成的ItemType被解释为AtomicOrUnionType。所需的类型AtomicOrUnionType与如果从(AT,AtomicOrUnionType(为真。
总之,结果是表达式3 instance of xs:positiveInteger
返回false(因为xs:integer
不是从xs:positiveinteger
派生的(。
最后,当函数参数的预期类型为xs:positiveInteger
,并且函数调用提供值3时,则§3.1.5.2中的函数转换规则将发挥作用。它们允许从提供的值到所需类型的各种转换,但从xs:integer到xs:ppositiveInteger的"下转换"不是其中之一。所以这是一个错误:
如果在上述转换之后,结果值不匹配根据SequenceType Matching规则的预期类型,a引发类型错误[err:XPTY0004]。
正如我所说,我不喜欢这些规则,并多次尝试更改它们。但它们是明确的,任何不遵循它们的产品都是不合格的。
https://www.w3.org/TR/xpath-31/#promotion指定允许的促销类型:
数字类型促销:
xs:foat类型的值(或通过从xs:foat(可以升级为xs:double类型。结果是xs:与原始值相同的双值。
xs:decimal类型的值(或通过限制从xs:decimal(可以升级为xs:foat或xs:双。这次促销的结果是通过铸造原始值转换为所需类型。这种促销可能会精度损失。
对于其他类型,您必须显式使用构造函数,例如local:int(xs:int(1))
。
您可以将数字文字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 :)
您可以使用xdmp:type()
报告返回的值为positiveInteger
类型
xquery version "1.0-ml";
declare function local:pos-int($n as xs:positiveInteger) { $n };
xdmp:type(local:pos-int(1))