首页 > 代码库 > xml学习笔记 6.XQuery

xml学习笔记 6.XQuery

XQuery xml query 是一种专门用于xml半结构化数据的查询语言,是W3C的推荐的标准语言。

XQuery是有一些SQL专家制定的,基本语法与sql语句非常相似。比xslt更加简单。


FLOWR语句与select语句相对应,完成对xml数据的查询,筛选和排序。FLOWR是指FOR,LET,WHERE,ORDERBY,RETURN五种语句。其中可以使用XPATH路径表达式以及xpath中的内置函数,各种自定义的函数,和命名空间。


for子句:

for $b in doc("bib-demo1.xml")/bib/book 
for。。。in。。。相当与sql中的select。。。from。    $variable_name 表示声明一个变量,然后在 in ...的范围内进行循环遍历取值赋值给变量,然后进行之后的操作。 in后跟的是一个xpath的表达式,  doc("...")表示文本文档,是xpath中的内置函数。


LET子句:

let $i as xs:integer := 100 
相当与sql中的DECLARE和SET语句,声明一个变量并给其赋予一个初值。as后接数据的类型,一般在xs命名空间中的基础类型。 :=表示赋值。


WHERE语句:

where $b/author/last="Stevens"
相当与sql中的where语句。 判断式的前半部分为一个xpath表达式,后半部分为判断的值。若使用一个值即xpath作为操作数进行判断,若为空序列返回false,若序列第一个项为节点则返回true,若序列只含有一个单元子,若类型为xs:boolean,直接返回;若为xs:string等,则长度为0返回false,否则返回true;若为数值类型,则为0返回false,其他为true。


ORDERBY语句:

order by  $a/last, $a/first  descending

进行排序,缺省为ascending。还可以设置为descending。可以设置多个排序标准,首先按照第一个标准进行排序,对于相同的情况时,在按照后续的标准进行排序。


RETURN语句:

输出语句。在整个语句中,为每一个结果集中的每一项进行一次输出。可以进行如何文本格式的输出。

返回元素:

return <income>{$salary}</income> 
return element income {$salary} 


返回属性:

<book year="{ $b/@year }"/>
return <shoe size="As big as {$hat/@size}"/>

return element person {	attribute gender {$i},$j}

{}大括号内的值为计算的值,可以在任何地方使用,包括引号内。。。

可以使用条件表达式:

some $s in $S satisfies $s/C            
 exists($S[C])
every $s in $S satisfies not(C)
not(some $s in $S satisfies C)
element gender {if (node-name($node) cast as xs:string="husband") then "male" else "female"}

可以使用typeswitch操作,进行分支选择,但判断的是类型而不是值:

typeswitch($customer/billing-address)
   case $a as element(*, USAddress) return $a/state
   default return "unknown" 

可以定义函数。

declare function HelloWorld() as xs:string
return "Hello World!"

举几个栗子:


  列出2005-12-24日从North Pole出发的所有航班(dataQ1.xquery),将结果按照flightId进行排序输出;

<all>{for $p in doc("Data.xml")/doc/Flightwhere $p/source = "NPL" and $p/date = "2005-12-24"order by $p/flightIdreturn $p }</all>

查询连接任意两个机场的航班(如果存在),并输出机场名称对、以及所有航班的编号列表;(机场名称对,按字母升序表示,比如(AMS, BDP))

declare function local:getFlights(
 $pa as xs:string,
 $pb as xs:string
  )
  as element()*
{
    for $i in doc("Data.xml")/doc/Flight[contains(string(),$pa)][contains(string(),$pb)]
    return
            <flightid>{ string($i/@flightId) }</flightid>
};

<all>
{
for $a in doc("Data.xml")/doc/Airport
for $b in $a/following-sibling::Airport  
where (doc("Data.xml")/doc/Flight[contains(string(),$a/@airId)][contains(string(),$b/@airId)])	

return 	
		<pair>
			<airport>
			{if ($a/@airId > $b/@airId) then string($b/@airId) else string($a/@airId) }
			</airport>
			<airport>
			{if ($a/@airId > $b/@airId) then string($a/@airId) else string($b/@airId) }
			</airport>
			<Flights>{local:getFlights(string($a/@airId),string($b/@airId))}</Flights>
		</pair>
		
}
</all>
这里要使用函数进行嵌套查询。。。element()后的*表示其可以返回多个元素,而在参数中也可以写成 $pa as xs:string?  表示参数可以使用也可以不使用。


按照2005-12-24日机场繁忙程度(计算进出旅客总数)列出机场(忽略没有旅客进出的机场)、以及其进出旅客总数(dataQ3.xquery

declare function local:getFlight()
  as element()*
{
    for $a  in doc("Data.xml")/doc/Reservation[./date = "2005-12-24"]
    for $b  in doc("Data.xml")/doc/Flight
    where $b/@flightId = $a/flightRef
    return	$b  
};
declare function local:getNum()
  as element()*
{
    for $i in doc("Data.xml")/doc/Airport
    return	
			<NUM>
			{$i}
			<passNum>{count(local:getFlight()[./source=$i/@airId]) + count(local:getFlight()[./destination=$i/@airId])}</passNum>
            </NUM>
};

<all>
{
(:仔细观察了Data后,这里只有4个乘客啊,难道就使用这4个乘客进行计数,其他所有的飞机上都没有人?:)
for $x  in local:getNum()[./passNum > 0]
order by $x/passNum
return 	$x 		
}
</all>
函数中如果返回的是一个集合,则可以直接使用for对其中元素进行遍历,而且也可以直接加【】进行判断xpath的判定。

查询所有乘客去得最多的前三名目的地(dataQ4.xquery

declare function local:getFlight()
  as element()*
{
    for $a  in doc("Data.xml")/doc/Reservation[./date = "2005-12-24"]
    for $b  in doc("Data.xml")/doc/Flight
    where $b/@flightId = $a/flightRef
    return	$b  
};
declare function local:getNum()
  as element()*
{
    for $i in doc("Data.xml")/doc/Airport
    return	
			<NUM>
			{$i}
			<passNum>{count(local:getFlight()[./destination=$i/@airId])}</passNum>
            </NUM>
};

declare function local:get3Airport() as element()*
{
for $x  in local:getNum()
order by $x/passNum descending
return 	$x 	
};

<all>
{
(:仍然使用这4个人来当做所有游客:)
for $y in local:get3Airport()[position()<4]
return  <TOP3>{$y/Airport/name}</TOP3>
}
</all>
那个w3c上的栗子是在逗吗?坑我半天,蛋疼。