8、类型系统(XQuery):
(1)预定义的 XQuery 类型包括:
http://www.w3.org/2001/XMLSchema 定义的内置类型,预定义前缀 xs。
http://www.w3.org/2004/07/xpath-datatypes 定义的类型,预定义前缀 xdt。
(2)Instance of 关键字可以判断某个值是否是指定的类型,如
Select @x.query('1 instance of xs:integer')
Select @x.query('/a[1] instance of element()') –判断是否是元素
Select @x.query('/a[1]/@type instance of attribute()') –判断是否是属性
Select @x.query('/a[1]/@type instance of attribute(type)') –判断是否type属性
(3)对于 xdt 命名空间中定义的数据类型:
这些数据类型用于 XQuery 静态类型化,在创建 XML 架构集合时无法使用这些类型。
查询非类型化的 XML 时,元素节点的静态类型或动态类型都是 xdt:untyped,属性值(注意是“值",即 data(属性),其实 data(节点) 返回的也是 xdt:untypedAtomic 类型)的类型是 xdt:untypedAtomic。如
declare @x xml
set @x = '<a type="int">10</a>'
select @x.query('/a[1] instance of element(a, xdt:untyped?)') –返回:true
select @x.query('data(/a/@type) instance of xdt:untypedAtomic') –返回:true
注意:倒数第二句中的 element(a, xdt:untyped?),验证是否是 xdt:untyped 类型,不能直接写 '/a[1] instance of xdt:untyped'
(4)data() 与 string() 函数的区别:data() 返回节点的类型化值,string() 返回节点的字符串值。
9、序列类型匹配(使用 instance of 操作符)
(1) 序列是否为空,使用 empty(),如
Declare @x xml
Set @x = '<root>1</root>'
Select @x.query('/root[1] instance of empty()')
注意:instance of 只能接受具有一个元素或为空的序列
(2) 带问号和不带问号的区别
Create XML Schema Collection SC As N'
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<element name="root" nillable="true" type="byte" />
</schema>'
Declare @x xml(SC)
Set @x = ''
Select @x.query('data(/root[1]) instance of xs:byte') – 返回:false
Select @x.query('data(/root[1]) instance of xs:byte?') – 返回:true
后一句加了“?"即返回 true。可见问号的作用类似于 C# 中的可空类型声明。
(3) 比较节点类型
l item() 与序列中的任意项匹配
l node() 确定序列是否为节点(node() 可匹配任意节点,如文本、属性、注释、处理指令等,这与 * 号不同)
l processing-instruction() 是否为处理指令
l comment() 是否为注释
l document-node() 是否为文档节点(2005不支持)
l text() 是否为文本节点
(4) 元素测试
l element()
l element(elementName)
l element(elementName, elementType?)
l element(*, elementType?)
(5) 属性测试
l attribute()
l attribute(AttributeName)
l attribute(AttributeName, AttributeType?)
l attribute(*, AttributeType?)
10、错误处理
除 XQuery 聚合函数中的溢出条件和 XML-DML 验证错误,其它的动态错误(运行时错误)都映射到一个空序列。这会导致一些问题,需要注意,如
Declare @x xml
Set @x = '<root><a>100</a><b>200</b><c>Hello</c></root>'
Select @x.query('avg(/root/*)') – 返回 150
最终结果返回 150,并不是因为忽略了字符串值“Hello",而是在将字符串转换为 double 值时发生错误,返回一个空序列,而 avg 函数会自动忽略空序列。
在谓词中使用 not(如 //someNode[not(Exp)])将会导致动态错误,但是会返回一个空序列。将 not 应用于空序列(not(()))会返回 true。
11、XQuery 中的注释使用 (: :) 包括起来,如 (: 注释 :)
12、XQuery 与静态类型化
(1) 在类型名称后添加 ?、* 和 + (如上面的 xs:integer?)的意义:
其实,这跟在 C# 中的 int? 差不多,都会产生一个新的类型。因为XQuery 中操作的是序列,所以 xs:integer? 表示包含零个或一个整型值的序列,xs:integer+ 表示包含一个或多个整型值的序列,xs:integer* 表示包含零个或个整型值的序列。而序列包含的项目的个数就是 MSDN 中所谓的“基数"。
(2) XML 类型中关于子类的定义:如果类型 S 包含的所有值都是类型 T 的实例,则 S 是 T 的子类。
(3) 对于架构中指定的联合类型,在运算时最好将联合类型强制转换为联合类型中包含的某个指定类型。