XML查询语言(XQL) 是用于定位和过滤XML文档中元素和文本的符号。它是XSL模式语法的自然扩展,为指向特定的元素或查找具有指定特征的节点提供了简明的可以理解的符号。XQL是最早由Microsoft,Texcel等公司提出的一种XML查询语言,前面我们已经提到,XSL模式语言提供了一种描述一类将需要处理的结点的好方法。实际上是通过XPath来实现的,当然XSL是说明性的,而非过程性的。但XSL也有许多不足之处,如不支持表达式,不能在结点间进行等值连接,对多个分散的XSL文档没有一个形式化的查询机制,没有支持聚集操作等。XQL则在XSL基础上提供了筛选操作,布尔操作,对结点集进行索引,并为查询、定位等提供了单一的语法形式。因而在一定意义上可将XQL看作XSL的超集。
XQL主要针对解决以下四个问题域而提出:
(1)在单个XML文档中进行查询。如在XML浏览器和编辑器中对所处理的XML文档进行查询。另外, Script也能利用这种性质给出一个非过程性的存取文档数据和结构的方法。
(2)在XML文档集中进行查询。如在XML文档仓储(Repository)中进行查询。
(3)能在XML文档间对结点进行定位。在HTML文档中,常常用HyperLink来定位其它文档,而在已有的XML中,链接形式更多样化,有TEL Links, HyTime Links,XML Linking,这些都允许链接有更大的灵活性。XQL则主要是想通过给出一已知位置的相对路径,或通过一绝对路径来在文档中定位任一结点。
(4)以字符串语法形式表达,使其能在URL中应用在XSL模板中及其它地方应用。
在介绍例子查询之前,对XQL中的一个重要的概念:Context 作一了解。Context即查询指定的一系列结点。XQL的基本语法模仿了URI(Unified Resource Identifier)目录导航语法,通过Context,XQL可以指定XQL查询是以XML树结构中哪一层开设作为查询范围(例如,从树的根结点或儿子结点)。XQL中以 / 表示根环境(Root context),以./ 表示当前环境(Current context)。
XQL简单例子及分析
举一个具体的例子来说明XML的应用,首先我们来建立一个如下的XML文档:
<?xml version="1.0" encoding="GB2312" ?>
<订单集合>
<订单>
<客户>
美博进出口公司
</客户>
<注释>
主要用来进出口各种办公用具:包括各种笔盒、本子、笔等等。
</注释>
<清单列表 n=2>
<清单 数量=100 总金额="24.00">
<产品 标记="STA" 名称="铅笔" 价格="0.24"/>
</清单>
<清单 数量=200 总金额="120.00">
<产品 标记="STA" 名称="钢笔" 价格="0.60"/>
</清单>
</清单列表>
</订单>
<订单>
<客户>
金鼎进出口公司
</客户>
<注释>
主要用来进出口各种化妆用具:包括各种眉笔、口红、护肤霜等等。
</注释>
<清单列表 n=2>
<清单 数量=100 总金额="124.00">
<产品 标记="BMA" 名称="眉笔" 价格="1.24"/>
</清单>
<清单 数量=200 总金额="720.00">
<产品 标记="BMA" 名称="口红" 价格="3.60"/>
</清单>
</清单列表>
</订单>
</订单集合>
下面我们来建立几个实际的查询例子,根据我们在XPath中的学习的经验可以知道,元素集合可以用路径操作符("/"或"//")指定。路径操作符将左部作为查询来源的参数集合,右部表示需要查询的元素。子女操作符("/")查询左部元素集合的直接子女集合,后代操作符("//")查询左部元素集合的任意后代集合。
例子1:
查询:
file://客户
结果:
<xql:result>
<客户>
美博进出口公司
</客户>
<客户>
金鼎进出口公司
</客户>
</xql:result>
||||||我们知道,属性名称用"@"符号开头。XQL设计公平对待属性和子元素,在可能的情况下,两种类型的能力是等价的。注意:属性不能包含子元素。因此,在查询中属性不能使用路径操作符。否则将导致语法错误。同样地,属性天生没有顺序,索引不能用于属性。
通过对集合增加过滤子句"[ ]",可以对任何集合进行限制和分枝。过滤是SQL中包含ANY语义的WHERE子句的模拟。过滤子句中包含了一个查询,称为子查询。子查询计算出布尔值,对集合中的每一个元素进行测试。集合中未通过子查询测试的元素将从结果集合中省略。为方便起见,如果集合放于过滤之中,或者如果集合中包含元素,则产生布尔值TRUE;如果集合为空,则产生FALSE。本质上,如author/degree的表达式表示集合到布尔值的转换函数,象如下虚构的"存在一个"方法:
author[.there-exists-a(degree)]
注意,在表达式的给定级别上可以出现任何数目的过滤,但空过滤是不允许的。同时需要注意的是,在XQL语言中,"=" 符号用于相等判断,"!="用于不相等判断。作为选择,$eq$和$ne$ 也可用于相等和不相等。单引号或双引号可以用于在表达式中分隔字符串,使得在脚本语言中创建或传递XQL变得更为容易。
对于比较元素值而言,暗含了value()方法。也就是说,last-name < 'foo'实际上表示last-name!value() < foo。这有点象VB中对对象指定缺省的属性一样,比如一个Text对象Text1,Text1="中国"相当于Text1.text="中国"。
请注意,过滤总是和上下文相关的。即:表达式book[author]表示对每一个找到的book元素,查看其是否包含author子元素。同样地,book[author = Bob ] 表示对每一个找到的book元素,查看其是否包含命名为author,且值为'Bob'的子元素。你也可以通过使用"."(句点) 查看当前上下文的值。例如,book[. ='古龙' ]表示对每一个找到的book元素,查看其值是否等于'古龙'。
例子2:
查询
file://产品[@标记='BMA']
结果:
<xql:result>
<产品 标记="BMA" 名称="眉笔" 价格="1.24"/>
<产品 标记="BMA" 名称="口红" 价格="3.60"/>
</xql:result>
例子3:
file://订单[客户='美博进出口公司']/产品
结果:
<xql:result>
<产品 标记="STA" 名称="铅笔" 价格="0.24"/>
<产品 标记="STA" 名称="钢笔" 价格="0.60"/>
</xql:result>
布尔表达式可以在子查询中使用。例如,可以使用布尔表达式查找特定值的节点集合,或者特定范围的节点集合。布尔表达式采取${op}$的形式,而{op}可以是任何{b|a}形式的表达式-即:操作符接收左值和右值参数,返回布尔结果。应用可以根据需要提供附加的布尔操作符。
例子4:
查询
file://产品[@标记='BMA'|@标记='STA']
结果:
<xql:result>
<产品 标记="STA" 名称="铅笔" 价格="0.24"/>
<产品 标记="STA" 名称="钢笔" 价格="0.60"/>
<产品 标记="BMA" 名称="眉笔" 价格="1.24"/>
<产品 标记="BMA" 名称="口红" 价格="3.60"/>
</xql:result>
这里,我们需要从上面的例子入手来描述XQL的语法特点,首先需要注意的是,XQL表达式返回的集合在定义范围内保持文档顺序,层次结构和标识。即:元素集合总是无重复地以文档顺序返回,属性集合将无重复地返回,但由于属性无顺序地定义,返回集合并不意味着顺序。