</everyone>
上面的表达式将会返回一个正确的xml文档。请注意在这个例子中的标签 <everyone> 和 <who> ,是原样返回的。同时需要注意的是为了使return语句正常执行,必须包含一个单一的实体。
<everyone>
<who> <name> hari </name> </who>
<who> <name> john </name> </who>
...
<who> <name> leu </name> </who>
</everyone>
请注意上面的查询返回的是<name>元素。如果我们想仅仅显示名字的值而不显示出任何的标签该如何做呢? 我们需要使用text()函数。在上面的查询中,将"//name" 改为"//name/text()" ,将"$e"改为"$e/text()"。下面的查询就使用了这种方法。
for $e in document ("emp.xml")//name
return $e/text()
这个查询返回了一系列没有标签的名字。这说明xquery查询是可以根据用户或者应用程序所预期的情况定制的。xquery是从一种叫做quilt的语言中发展起来。
hari
john
...
leu
这里有另外一个例子。
for $d in distinct(document("emp.xml")//dname)
let $e := document("emp.xml")//entry[dname = $d]
return
concat($d/text(), " department has ", numformat("##", count($e)),
" employee(s).")
将会输出下面的结果: credit department has 1 employee(s).
toys department has 2 employee(s).
shoes department has 1 employee(s).
audit department has 1 employee(s).
条件表达式(conditional expression)
在前面的例子中我们已经初步接触了一些if then else语句的用法,下面我们来具体看看他们的语法格式:
if <条件表达式> then <表达式一> else <表达式二>
在条件表达中,条件表达式应当赋值为布尔值,或者是一个能被转换为布尔值的类型。如果值是为真,整个条件表达的结果的值和表达式一的值一样。否则和表达式二一致。下面提供给读者一个简单的例子:
<report>
for $e in document("emp.xml")//entry
return
<entry>
$e/name,
<proposedsal> if ($e/salary .>=. 60000) then 100000 else 200000</proposedsal>
</entry>
</report>
元素构造器(element constructor)
在写查询语句的时候,你可能需要创建新的元素作为输出的一部分。元素构造器便提供这样的功能。一个简单的元素构造的例子如下:
<newelement>xquery language</newelement>
新元素的内容可以是指定的,也可以是计算产生的。
函数调用(function call)
这里函数的概念和其他程序设计语言中的函数概念是完全相同的。我们来看一个例子:
下面的函数返回xml文档的最大深度。
随后是一个计算partslist.xml 文档深度的调用。
define function depth(element $e) returns xs:integer
{
{-- an empty element has depth 1 --}
{-- otherwise, add 1 to max depth of children --}
if (empty($e/*)) then 1
else max(for $c in $e/* return depth($c)) + 1
}
depth(document("partlist.xml"))
高级话题与应用
求和
在xquery当中,求和通过let和sum可以很简便的完成,在sql中,要使用"group by"与"having"语句。但是在sql当中,"group by"和"having" 只能和一个from语句对应,而在xquery当中可以使用多个let语句。下面的例子是按照部门返回工资总额。
<deptpayrolls>
for $d in distinct(document("emp.xml")//dname)
let $s := document("emp.xml")//entry[dname = $d]/salary
return
<deptpayroll>
$d,
<sumsal> sum($s) </sumsal>
</deptpayroll>
</deptpayrolls>
如果想得到大于等于70000的工资,我们应当做下面的查询。
<specialdepartments>
for $d in distinct(document("emp.xml")//dname)
where every $s in document("emp.xml")//entry[dname = $d]
satisfies ($s/salary >= 70000)
return
<deptavg>
$d,
<avgsal> avg(document("emp.xml")//entry[dname = $d]/salary) </avgsal>
</deptavg>
</specialdepartments>
值得注意的最重要一点是。在kweelt当中我们使用".>=." 而不是使用 ">="e uses ".>=."。最大的障碍是kweelt不支持数词。因此 "every x satisfies c(x)" 在kweelt不起作用。
设想一个等价表达式"not(some x satisfies not(c(x))" 尽管这样还是含有数词,但是它提供给我们一种间接的方式:首先我们在$s中收集满足not(c(x))的元素x,在where从句中使用"not exists ($s)" 来过滤掉已经通过for语句但是不符合这个要求的部分。剩余的部分就是所需的,并且将在return语句执行后被释放出来。因此我们得出了下面的查询。
<specialdepartments>
for $d in distinct(document("emp.xml")//dname)