数据库应用-半结构化数据访问-2

来源:互联网 发布:mac 文件夹隐藏与显示 编辑:程序博客网 时间:2024/06/09 20:13

XQuery:FLWR-expression

Syntax:

for var1 in expression1,...,varn in expressionnlet varn+1:=expressionn+1,...,varn+m:=ausdruckn+mwhere condition expressionorder by expression ascending/descendingreturn xmlexpression

for是不是很像c里的循环,其实他就是循环,他循环遍历树,对每个点进行判断,满足要求的则返回节点,不满足的则跳过
let就是单纯的声明和定义变量
where是可选的,用来描述条件
return表示返回的结果,他的返回值必须符合XML文档的模式

例子

Query1:所有由Addison-Wesley于1991年后出版的书(year,title)

<bib>{for $b in document("http://www.bn.com")/bib/bookwhere $b/publisher = "Addison-Wesley"    and $b/@year > 1991return     <book year={$b/@year}>    {$b/title}    </book>}</bib>

问题:
1.如果其中一本书有多个title会怎么样??
会逐一列出
2.如果有一本书没有标明publisher会怎么样??(Höhere Robustheit)
不会报错,返回空值,不输出
补充:
Pendant zur FROM-Klausel(??)
Umgang mit Attributen(通过变量进行操作)
Pfadausdrücke in allen Anfrage-Bestandteilen(路径表达可以在访问的任意地方使用)
问题扩展:
假如我们并不知道:
1.title的具体位置在哪?
2.哪些元素含有字符串”Addison-Wesley”
可以使用:
b//titleb/*=”Addison-Wesley”//这个有点不懂??为什么只往下一级??
Query2:把每本书的title和autor放在result元素中输出

<result>{for $b in document("http://www.bn.com")/bib/bookreturn     <result>        {$b/title}        {//或直接使用$b/autor            for $a in $b/autor            return $a        }    </result>}</result>

问题:
1.如果有本书,含有多个title元素,会怎么样呢?
2.区别下面代码和原答案的不同:

<results>{for $b in     document("http://www.bn.com")/bib/book        $t in $b/title,        $a in $b/author    return         <result>            {$t}{$a}        </result>}</results>

Query3:在result元素中输出每个作者及其对应的著作的名字

<results>{for $a in distinct-values(document("http://www.bn.com")//author)return    <result>        {$a}        {for $b in document("http://www.bn.com")/bib/book        where value-equals($b/autor,$a)        return $b/title}    </result>}</results>

值得注意的地方:
1.文档重组(Umstrukturierung des Dokuments)//注意啥??
2.实现了join
3.使用了内置方法
distinct-values(…)
//注意并不存在针对元素的distinct()方法
value-equals()
这个不仅要求节点的值相同还要求节点有相同的结构
**Query4:**book1中含有多少个top-level Sections?
//top level在这里是表示什么??直接用”//section”不行吗??

<top_section_count>{count(document("book1.xml")/book/section)}</top_section_count>

值得注意的地方:
FLWR里使可以用Aggregate方法的哦
(zählen von Dokumentbestandteilen??)
//zählen von表示什么意思??
Query5:输出所有的至少含有一个作者项的书的名字和作者名,如果作者的人数大于两个,那么只输出前两个,其他用et-al代替。

<bib>{for $b in document("www.bn.com/bib.xml")//bookwhere count($b/author)>0return    <book>        {$b/title}        {for $a in $b/author[position()<=2]        return $a]        {if(count($b/author)>2)        then <et-al>        else()}    </book>}</bib>

值得注意的:
这回路径表达使用了介词
另外还有条件语句
而且这回的Aggregate方法是在where中使用
Query6:按照字母表顺序输出所有1991年后由Addison-Wesley出版的书的名字和出版年份

<bib>{for $b in document("www.bn.com/bib.xml")//bookwhere $b/publisher = "Addison-Wesley"    and $b/@year > "1991"order by $b/titlereturn    <book>        {$b/@year}        {$b/title}    </book>}</bib>

XMLSpy输出的是属性的话得到的也是属性//好像是废话
(XMLSpy macht aus Attributen wieder Attribute)

AttributElement:<year>string($b/@year)</year>ElementAttribut:<book year="string($b/year)">

所以如果要把一个属性按照元素的方式输出的话,那么就要方法来生成一个元素,比如:string($n/@attib)
问题:
1.如果输出的格式不符合XML的规定呢??
会报错哦
2.如果有一本书,他有多个名字呢?要怎么排序??
不知???
但比较好得做法是使用:order by \$b/title[1]
/*
“stable order by…”
-Dokument-Reihenfolge bleibt erhalten bei Elementen mit gleichem Sortier-Schlüssel
*/
另外上面连续用来两次的\$b/title这样的效率比价低
//会吗??如果会的话,也就是说我前面的想法是错的,他的语句应该是一句一句走得,for语句结束后b就应该获得了所有的目标项,如果是这样的话那么上边第二个例子应该怎么解释,而且这里的输出也应该会变成先把所有的year输出后再输出title啊???还是说b项相当于容器,然后return自带遍历功能???
总之改进的方法就是使用let:

<bib>{for $b in document("www.bn.com/bib.xml")//booklet $t:=$b/titlewhere $b/publisher = "Addison-Wesley"        and $b/@year > "1991"order by $treturn     <book>        {$b/@year}        {$b/t}    </book>}</bib>

//也没看出有优化啊,难道每调用一次$b/title他都重新遍历一次不成??
/*这是解释,没看懂???
Beide Varianten leisten dasselbe.
Bei der zweiten Variante muss die Attribut-Generierung unmittelbar hinter dem Beginn-Markup kommen.
*/
Query7:一本包含有元素的书,如果他元素的tag(就是这个< Name >)是以or结尾的,那么输出这本书的名字和这个元素

for $b in document("www.bn.com/bib.xml")//book,    $e in $b/*where ends_with(local-name($e), "or")return    <book>        {$b/title}        {$e}    </book>

//不对啊 星星只往下一层啊,不是不全面吗???
值得一提的是:
用了一些方法哦像ends_with(),local-name()啊
打破了Schema信息和数据信息的界限
//其实以前不是一直都在处理Schema信息吗?虽然是默认的处理就是了

结构转换

相应与数据表达时的不同形式,xml的结构也可能不同,具体见下图:
//图两张
那么他们之间要怎么进行转换呢???

<publication>{for $v in document(biblio_document.xml)/biblio/*where $v/year > 1989return     <type>{local-name($v)}</type>    $v/title}</publication>

反过来:

let $step:=document("beispiel.xml")/publication/type[1]/text(),    $x:=document("anderes.xml")/biblio/$stepreturn    $x/nextStep

//第二个没懂,哪里跳出来的nextStep啊???

例子

继续例子
Query8:找出每本书的最低价格,并把他放在minprice元素中输出,minprice有一个属性,为title

<results>{let $doc:=document("prices.xml")for $t in distinct-values($doc//book/title)let $p := $doc//book[title=$t]/pricereturn     <minprice title={$t/text()}>        <price>{min(decimal($p/text()))}</prive>    </minprice>}</results>

decimal()是必须得因为他把字符串转化为数字类型,如此才能使用min().
Query9:给book1文档建立目录,只保留section元素和它的title
先插个图介绍filter:
//插图

<toc>{let $b := document("book1.xml");return     filter($b//section|$b//section/title|$b//section/title/text())}</toc>

Query10:获取第一个procedure元素下与前两个incision元素之间的所有节点

<critical_sequence>{let $proc:=//procedure[1]for $n in $proc//node()where $n follows($proc//incision)[1]    and $n precedes($proc//incision[2]return     $n}</critical_sequence>

值得一提的是:
proc/node()proc//proc//*????
//插图一张,看一下其他常见的方法
Query11:输出所有用户的名字,并且这些用户应该对所有的item都有出价(Namen all User, die ein Gebot für jedes Item abgegeben haben)

<frequent_bidder>{for $u in doucment("user.xml")//user_tuplewhere    every $item in document("items.xml")//item_tuple        satisfies      some $b in document("bids.xml")//bid_tupel          satisfies        ($item/itemno=$b/itemno and $u/userid=$b/userid)return     $u/name}</frequent_bidder>

值得一提的是:
every … satisfies …
some … satisfies …
//这个例子的开头,课件里还写着“基本的DTD”这样的字样,不知是啥意思???
(zugrundeliegende DTD)
Query12:又是变形课,看一下如何重第一张图变成第二张吧
//我是图片1S47
//我是图片2S48

define function one_level(element $p) returns element{<part partid={$p/@partid} name={$p/@name}>{    for $s in doucment("data/parts-data.xml")//part    where $s/@partof=$p/@partid    return one_level($s)}</part>}<parttree>{for $p in document("data/parts-data.xml")//part[empty(@partof)]return one_level($p)}</parttree>

值得一提的是:
1.用了递归哦
2.定义了方法one_level(element $p)
3.empty()
认真看看,上面的结果和要求的还是有一点区别的,当不含有子元素的时候,我们希望能过用简化的tag

define function one_level(element $p) returns element{if(count(document("data/partsdata.xml")//part[@partof=$p/@partid>0)then <part partid={$p/@partid} name={$p/@name}>{    for $s in document("data/parts-data.xml")//part    where $s/@partof = $p/@partid    return one_level($s)}</part>else<part partid={$p/@partie} name={$p/@name}/>}

或者可以这样:

define function one_level(element $p) returns element{if (empty(document("data/partsdata.xml")//part[@partof=$p/@partid])then<part partid={$p/@parted} name={$p/@name}/>else<part partid={$p/@partid} name{$p/@name}>{    for $s in document("data/parts-data.xml")//part    where $s/@partof = $p/@partid    return one_level($s)}</part>}

Query13:返回Magda的丈夫
基本的DTD:

<!DOCTYPE CENSUS[<!ELEMENT person(person*)><!ATTLIST person name ID    #REQUIRED                 spouse IDREF #IMPLIED                 job CDATA  #IMPLIED>]>
<result>{for $m in document("census.xml")//person[@name="Magda"]return     shallow($m/@spouse => person)}</result>

值得一提的是:
shallow表示只返回目标节点,所有的孩子都不被包括
还有就是箭头了
补充一些特殊的情况:
1.for和let可以多次出现
2.Variablenbindungen können dann aufeinander aufbauen.//??
3.for可以不要
4.let也可以不要
5.where还是可以不要
6.order by依然可以不要
7.geschachtelte Anfragen:
überall,wo Ausdruck erwartet wird

0 0
原创粉丝点击