430 likes | 696 Views
6. XQuery. XQuery ( XML Query )是一种专门用于 XML 半结构化数据的查询语言, W3C 于 2007 年 1 月 23 日正式发布了 XQuery 1.0 规范( XQuery 1.0 : An XML Query Language , http://www.w3.org/TR/xquery/ )。 与其他半结构化数据查询语言相比,由于它是 W3C 的推荐标准,所以受到了业界广泛的支持。目前,由不同的软件提供商所实现的 XQuery 软件包大约有 40 多种,适用于不同的开发语言、平台和环境。.
E N D
6. XQuery • XQuery(XML Query)是一种专门用于 XML 半结构化数据的查询语言,W3C 于 2007 年 1 月 23 日正式发布了XQuery 1.0 规范(XQuery 1.0 : An XML Query Language,http://www.w3.org/TR/xquery/)。 • 与其他半结构化数据查询语言相比,由于它是 W3C 的推荐标准,所以受到了业界广泛的支持。目前,由不同的软件提供商所实现的 XQuery 软件包大约有 40 多种,适用于不同的开发语言、平台和环境。
6.1 XML 数据查询语言 • 对于 XML 数据,查询语言的基本任务与关系数据库查询语言是相同的,主要包括如下几个方面: • 检索数据 • 聚集或汇总数据 • 连接来自不同数据源的数据 • 插入新的数据、更新或删除已有的数据 • 修改数据本身的结构 • 支持某些过程操作
6.1.1 从结构化数据查询语言 SQL 到半结构化查询语言 XQuery • SQL 结构化查询语言是用于关系数据库系统的标准查询语言,包括数据定义语言 DDL、数据操纵语言 DML、数据控制语言 DCL。 • 是否可以直接在 SQL 的基础上适当地增加一些特性或语法,使其用于查询 XML 数据呢?因为关系数据和半结构化所使用的底层数据结构完全不同,无法使用原有的 SQL。
SQL/XML • ISO/IEC 9075 系列标准的最新版本 SQL 2003 中,作为其中的第 14 部分“XML 相关规范(SQL/XML)”,第一次在 SQL 语言中正式引入了 XML 技术,它指出通用数据库管理系统应如何支持 XML 的存储、检索、转换,为基于 XML 的数据库应用的开发、集成、部署和运行提供了完整的集成解决方案。 • 这些 SQL/XML 功能的作用是将存储于关系数据库表结构中的数据映射为 XML 层次结构,而并不是对原始的 XML 数据进行查询检索。
XML 数据查询语言的特征 • 平台一致性 • 面向 XML 的(XML-Centric) • 具备集合处理的能力 • 易于使用 • 广泛的适应性
6.1.2 XQuery 的诞生 • 关系数据库中的 SQL/XML 无法完成对半结构化数据的查询检索。因此,出现了许多的半结构化数据查询语言,包括 XQL、XML-QL、XSQL、UnQL、StruQL、YATL、LOREL、以及 Quilt,其中 Quilt 是 XQuery 的前身。 • Quilt 最初作为用户级语法的测试工具,在定义需求、用例以及底层数据模型和代数方面进行了很多积极的努力,它本身借用了其他半结构化查询语言的一些优点,比如引入了路径表达语法、引入了变量绑定、提供了构造查询结果的语句、支持嵌套查询等。
XQuery 1.0 • 2007 年初,XML 查询工作组提交了正式的 XQuery 1.0 规范。 • XQuery 是一种用于文件和数据库中基于 XML 文档内容的新型查询语言,构建于 Quilt 查询语言的基础之上,从而综合了其他一些查询语言的优势和特点。 • XQuery 是由一些 SQL 专家制订,它的出现是因为 SQL 这种用于关系数据查询的语言无法完美地处理 XML 文档。
XQuery 的特点 • 作为 W3C 发布的一种规范,XQuery 与 W3C 所发布的其他规范之间具有很好的兼容性,比如 XQuery 使用与 XML Schema 一致的内置数据类型系统、并支持使用 XML Schema 提供自定义的类型信息、XQuery 1.0 依靠 XPath 2.0 路径表达式进行对层次化文档的操作、XQuery 1.0 与 XPath 2.0 使用一组公共的操作符和函数。 • 与 XSLT 相比,XQuery 具有以下的特征: • 易于使用 • 更加简洁 • 强类型语言 • 更广泛地使用场景
6.1.3 XML 格式的 XQuery 查询语言 • 查看 XMLSPY 中的 XQuery 文档。 • XQuery 也支持面向机器处理的 XML 格式,这就是 XQueryX(XML Syntax for XQuery 1.0 (XQueryX))。 • XQueryX 是 W3C XML 工作组开发的另一个规范,它是一种通过 XML 语法描述 XQuery 的标记语言。 • XQueryX.xml for$tindoc("bib.xml")/bib/book/title return$t
6.2 XQuery 基本语法和相关概念 • XQuery 相当于查询 XML 数据的 SQL 语言,并且 XQuery 规范本身就是由一些 SQL 专家们制订,所以它的基本语法与 SQL 语言非常相似。 • 与 SQL 中的 select 语句向对应,XQuery 中提供了 FLOWR 语句,可以完成对 XML 数据的查询、筛选、排序。
6.2.1 XQuery 基本语法 for$bindoc("bib-demo1.xml")/bib/book let$t := $b/title, $a := $b/author where$a/last="Stevens" orderby$t return<result> { $t } { $a } </result> SELECT column_list FROM table_source ORDER BY order_by_expression WHERE search_condition <?xml version="1.0" encoding="UTF-8"?> <bib> <book year="1994"> <title>TCP/IP Illustrated</title> <author><last>Stevens</last><first>W.</first></author> <publisher>Addison-Wesley</publisher> <price> 65.95</price> </book> <book year="1992"> <title>Advanced Programming</title> <author><last>Stevens</last><first>W.</first></author> <publisher>Addison-Wesley</publisher> <price>65.95</price> </book> </bib> <result> <title>Advanced Programming</title> <author><last>Stevens</last><first>W.</first></author> </result> <result> <title>TCP/IP Illustrated</title> <author><last>Stevens</last><first>W.</first></author> </result>
FLOWR 表达式 • FLOWR 表达式是 XQuery 查询计划基本形式 • XQuery 查询计划的逻辑组成部分,其中包含: • FOR 子句、 LET 子句、 WHERE 子句、 ORDER BY 子句、 RETURN 子句 • XPath 路径表达式和内置函数 • 各种自定义函数 • 命名空间
for 子句 • SELECT ... FROM ... 用于指定从某个数据库表中检索若干列的内容;严格地说,这个操作的执行过程是,按照实际存储顺序(或索引结构)、依次访问该数据库表中的每一条记录,并从中取出指定列的内容,然后再执行后续的操作。如果单独考虑 SELECT ... FROM ...,它实际上是一个在目标数据集合中进行循环遍历的取值过程,以便对所取出的数据进行进一步的筛选和排序等操作。 • 在 XQuery 中,for 子句用于完成类似的工作,它也相当于高级程序设计语言中的 for 循环。
for 子句中的范围变量 • 在 for 子句中,$variable_name 表示声明一个范围变量(range variable),然后为这个范围变量指定取值范围的集合,依次进行绑定。 • 比如,flwor-demo1.xquery 中的“for$bindoc("bib-demo1.xml")/bib/book ”,这表示 $b 的取值范围为 bib-demo1.xml 中的两个 book 节点(使用了关键字 in)。在执行该查询计划时进行循环遍历取值,分别取 book1、book2,以便对所取出的数据节点进行进一步的筛选和处理等操作。
let 子句 • 类似于 SQL 中的 DECLARE 和 SET 语句,用于定义一个局部变量,并为其赋值。 Declare @i as int Set @i = 100 let$ias xs:integer := 100 • let 中的普通变量与 for 中的循环变量不同,它的取值仅进行一次性地绑定,而不是循环依次绑定。
有关 for 和 let 子句的详细说明 • 参见 for-and-let.xquery。
6.2.3 where 语句 • where 语句可以指定一系列的判断条件,根据 for 和 let 语句所生成的变量绑定元组进行筛选。 • where 语句是可选的,并且判断条件应该得到一个有效的布尔值(true 或 false),如果判断条件的计算结果为 true,则保留该元组;否则,则放弃该元组。
where 语句的使用 • 比如下面的两个查询是完全等价的。 for$bindoc("bib-demo1.xml")/bib/book where$b/author/last="Stevens" return<result> { $b/title } </result> for$bindoc("bib-demo1.xml")/bib/book[author/last = "Stevens"] return<result> { $b/title } </result> • 可以使用 XPath 表达式中的判定谓词来取代 where 语句中的某些判断条件,有关 XPath 的判定谓词,曾在第 4 章中进行了详细地介绍。当然,从可读性的角度来说,建议尽可能使用前面一种方法书写。
where 语句中布尔值的计算 ① 如果操作数是一个空序列(( )),那么转换将返回 false。 ② 如果操作数是一个序列,并且其中的第一项是节点,那么转换将返回 true。 ③ 如果操作数是一个仅包含单个原子值项目的序列,并且这个项目的类型为 xs:boolean,那么转换将返回该项目的值。 ④ 如果操作数是一个仅包含单个原子值项目的序列,并且这个项目的类型为 xs:string、xs:anyURI、xs:untypedAtomic,那么对于长度为零的值,转换将返回 false;否则返回 true。 ⑤ 如果操作数是一个仅包含单个原子值项目的序列,并且这个项目的类型为数值类型,那么对于非零的值,转换将返回 true;否则返回 false。 ⑥ 在任何其他的情况下,转换将产生类型错误。
布尔值计算的示例 根据上述的规则,下面的 where 语句将返回 true: 规则 ②:where (<a/>,<b/>) 规则 ③:where ("true"castas xs:boolean) 规则 ④:where ("false") 规则 ⑤:where (123) 根据上述的规则,下面的 where 语句将返回 false: 规则 ①:where ( ) 规则 ③:where ("false"castas xs:boolean) 规则 ④:where ("") 规则 ⑤:where (0) 根据上述的规则,下面的 where 语句将产生类型错误: 规则 ①、规则 ② 和规则 ⑥(非空序列,并且包含多个项目,但第一个项目不是节点): where (123,<a/>)、where ("true"castas xs:boolean,<a/>)
order by 语句 • order by 语句是 XQuery 提供指定结果次序的功能;如果没有order by子句,结果的次序由 for 和 let 子句、以及排序模式决定。order by 语句中可以指定排序是 ascending 或 descending,缺省情况为 ascending 方式。 • 在 order by 语句中可以同时指定多个排序标准,首先按照第一标准进行排序,如果出现相等的情况,再依次按照后续的标准进行排序。
order by 语句的基本使用 • 对于排序,循环操作(使用 for 语句)是必需的。 for$bin fn:doc("bib.xml")/bib/book orderby$b/title return<result> { $b/title } </result> let$b := fn:doc("bib-demo1.xml")/bib/book orderby$b/title return<result> { $b/title } </result>
order by 语句的示例 • students.xml + students.xsd • orderby.xquery
return 语句 • 在 FLOWR 中,return 语句为候选结果集中的每一个项计算一次,这些计算结果连接形成 FLWOR 表达式的结果。 • return 语句返回结果的顺序由排序模式、或者 order by 语句决定。 • 可以输出任何文本信息,包括 html、xml、xhtml、纯文本等各种形式。 • XQuery 提供了一些构造方法,以便在查询中创建 XML 结构,即创建元素、属性、文档、文本、注释和处理指令节点。这些构造方法主要分为两大类:直接构造方法(类似于 XML 形式的表示方法);计算构造方法(使用带括号的表示方法)。
一、直接构造方法 • 直接构造方法就是直接在 XQuery 查询计划中合适的位置按照 XML 的格式编写相应的内容。 • XQuery 文件的后缀名通常为 .xq 或者 .xquery,并不是一个 XML 文档。经过 XQuery 查询引擎处理之后,将直接输出其中所包含的类似 XML 格式的直接编码,从而在结果 XML 文档中形成相应的组成部分(包括元素、属性、文本、以及注释等等)。
① 元素及其文本内容的直接构造 ... return<result> { $t } { $a } </result> <results> { for$bindoc(“bib-demo1.xml”)/bib/book let$t := $b/title, $a := $b/author where$a/last=”Stevens” orderby$t return<result> { $t } { $a } </result> } </results>
② 属性的直接构造 I. <shoe size="7"/> 结果为<shoe size="7"/> II. <shoe size="{7}"/> 结果为<shoe size="7"/> III.<shoe size="{( )}"/> 结果为<shoe size=""/> IV.<chapter ref="[{1, 5 to 7, 9}]"/> 结果为<chapter ref="[1 5 6 7 9]"/> V.let$hat := <hat size="23"/> return<shoe size="As big as {$hat/@size}"/> 结果为 <shoe size="As big as 23"/>
③ 其他内容的直接构造 let$salary := 1000 return <income xmlns = "http://mycompany.org"> <!-- From 2006 to 2007 --> <?basis time="monthly"?> {$salary} </income> 其结果为: <income xmlns="http://mycompany.org"> <!-- From 2006 to 2007 --> <?basis time="monthly"?> 1000 </income>
二、计算构造方法 • 直接构造方法存在一定的局限性。 • XQuery 中构造 XML 内容的另一种方法是计算构造方法,通过采用一系列的计算构造语法,可以构造各种各样的 XML 内容。
① 元素及其文本内容的计算构造 CompElemConstructor ::= "element" (QName | ("{" Expr "}")) "{" ContentExpr? "} " ContentExpr ::= Expr • 使用计算构造方法来构造元素,首先使用关键字 “element”,然后以硬编码的方式指定该元素的名称 QName(限定的名称,可以包含命名空间前缀)、或者使用表达式 (“{” Expr “}”) 动态地计算出该元素的名称,最后使用内容表达式 “{” ContentExpr? “}” 计算出该元素的内容(如果没有表达式 ContentExpr,则该元素为空元素)。 • 在 XML 中,元素可以包含子元素,所以某个元素的 CompElemConstructor 中可能嵌套地包含其他元素的 CompElemConstructor。
元素计算构造的示例 let$salary := 1000 return<income>{$salary}</income> let$salary := 1000 returnelement income {$salary} for$nodein (<student>WangFang</student>,<city>Beijing</city>) returnelement {concat("new", node-name($node))} {data($node)} <newstudent>WangFang</newstudent> <newcity>Beijing</newcity> for$nodein (<student>WangFang</student>,<city>Beijing</city>) return element {concat("new", node-name($node))} {element {concat("sub", node-name($node))} {data($node)} } <newstudent> <substudent>WangFang</substudent> </newstudent> <newcity> <subcity>Beijing</subcity> </newcity>
② 属性的计算构造 CompAttrConstructor ::= "attribute" (QName | ("{" Expr "}")) "{" Expr? "}" • 使用计算构造方法来构造属性,首先使用关键字 "attribute",然后以硬编码的方式指定该属性的名称 QName(限定的名称,可以包含命名空间前缀)、或者使用表达式 ("{" Expr "}") 动态地计算出该属性的名称,最后使用表达式 "{" Expr? "}" 计算出该属性的值(如果没有表达式 Expr,则属性值为空)。
属性计算构造的示例 for$nodein (<couple><husband>Tom</husband><wife>Alice</wife></couple>)/element() return element person { attribute gender {if (node-name($node) castas xs:string="husband") then"male"else"female"}, data($node) } <person gender="male">Tom</person> <person gender="female">Alice</person>
③ 其他内容的计算构造 CompTextConstructor ::= "text" "{" Expr "}" CompPIConstructor ::= "processing-instruction" (NCName | ("{" Expr "}")) "{" Expr? "}" CompCommentConstructor ::= "comment" "{" Expr "}" <result> { for$nodein (<student>WangFang</student>,<city>Beijing</city>) return element {node-name($node)} { data($node), comment {"appended-text"}, text {2+3}, processing-instruction pi-name {"some-pi"} } } </result> <result> <student>WangFang<!--appended-text-->5<?pi-name some-pi?></student> <city>Beijing<!--appended-text-->5<?pi-name some-pi?></city> </result>
条件表达式 IfExpr ::= "if" "(" TestExpr ")" "then" ExprSingle "else" ExprSingle ExprSingle ::= FLWORExpr | QuantifiedExpr | IfExpr • if-then-else.xquery some $p in //price satisfies $p > 10000 every $p in //price satisfies $p > 10000 some $s in $S satisfies $s/C exists($S[C]) every $s in $S satisfies not(C) not(some $s in $S satisfies C)
6.4灵活地使用 XQuery • XQuery 1.0 的类型系统及类型操作 • XQuery 1.0 中的类型系统与 XPath 2.0 的类型系统完全一致。 • 在 XQuery 中,增加了一些有关类型的操作,比如 typeswitch 操作符。typeswitch 操作符类似于高级程序设计语言中的 switch 语句,不同的是,它根据输入参数的类型来进行分支选择,而不是输入参数的值。 typeswitch($customer/billing-address) case$aaselement(*, USAddress) return$a/state case$aaselement(*, CanadaAddress) return$a/province case$aaselement(*, JapanAddress) return$a/prefecture defaultreturn"unknown"
在 XQuery 中编写自定义的函数 • 在 XQuery 中,除了使用内置函数之外,还允许用户声明他们自己的函数。函数声明需要指定函数的名称、参数名称及数据类型、以及返回值的数据类型。 • 函数定义的基本语法如下所示: FunctionDecl ::= "declare" "function" QName "(" ParamList? ")" ("as" SequenceType)? (EnclosedExpr | "external") ParamList ::= Param ("," Param)* Param ::= "$" QName TypeDeclaration? TypeDeclaration ::= "as" SequenceType xqueryversion"1.0"; declarefunction local:HelloWorld() as xs:string { "Hello World!" }; local:HelloWorld() xqueryversion"1.0"; declarefunction HelloWorld() as xs:string return"Hello World!" HelloWorld( )
modulenamespace hello = "http://example.org/hello-function"; declarefunction hello:HelloWorld() as xs:string { "Hello World!" }; declarevariable$hello:pi as xs:double :=3.141592653589793; module1.xquery xqueryversion"1.0"; importmodulenamespace mod1 = "http://example.org/hello-function"at"module1.xquery"; <result> <function-call>{mod1:HelloWorld()}</function-call> <showVariable>{$mod1:pi}</showVariable> </result> MainQuery.xquery 模块的定义以及导入 • 模块是一组函数或变量的命名的集合。可以将一组相关的函数和变量定义在某个模块中,然后在需要的时候导入并使用。 <result> <function-call>Hello World!</function-call> <showVariable>3.14159265358979</showVariable> </result>
在 XQuery 中声明命名空间 NamespaceDecl ::= "declare" "namespace" NCName "=" URILiteral xqueryversion"1.0"; declarenamespace here ="www.example.org"; declarefunction here:HelloWorld() as xs:string { "Hello World!" }; here:HelloWorld() xqueryversion"1.0"; declarenamespace here = "http://example.org"; <here:ele> Element </here:ele> <here:ele xmlns:here="http://example.org"> Element </here:ele> xqueryversion"1.0"; declaredefaultelementnamespace"http://example.org/names"; <ele> Element </ele> <ele xmlns="http://example.org/names"> Element </ele>
使用外部 XML Schema • 在 XQuery 中,有时候我们需要使用与目标 XML 文档相关联的 XML Schema 来提供数据的类型信息(XQuery 实际上是对经过模式验证后的信息集 PSVI 进行操作)。 • 有时候目标 XML 文档并没有指定任何关联的 Schema 模式,而需要使用某些外部 XML Schema 来完成两项任务。 • 第一,对输入的 XML 数据进行验证,从而确保原始数据的有效性,并充分地利用 Schema 中的结构信息完成相关的操作; • 第二,对输出的 XML 数据进行验证,从而确保所得结果的有效性。
导入和使用 Schema • 导入了一个没有目标命名空间的 Schema 文件,指定了该文件的位置,并将缺省的元素/类型命名空间指定为空。 • Schema-Import1.xquery • Schema-Import2.xquery importschemadefaultelementnamespace""at"http://example.org/xyz.xsd";
6.5 XQuery 用例分析 • 见 XMLSPY 和教材。