このドキュメントは、W3CのXML Query Use Casesのワーキングドラフトの翻訳です。正式なのはW3Cのサイトにある英語版であり、この翻訳ではありません。この翻訳は原文と技術的に等価なことを意図していますが、翻訳上の誤りが存在する可能性があります。
原文は次のURLで参照することができます:Copyright(c)2002 W3Cョ (MIT, INRIA, Keio), All Rights Reserved. W3C liability, trademark, document use, and software licensing rules apply.
このドキュメントは、XQuery利用シナリオを示したものです。
このドキュメントは、XQueryワーキングドラフトの2002年11月15日のバージョンに対応しています。このドキュメントのクエリは、XQueryワーキングドラフトのドキュメント作成の際に使用されたグラマーと同じグラマーで生成されたパーサを用いてパーシングされたものです。記述例(“Strong”)には、クエリが一つ加えられています。このクエリは、XML Schema Primerのレポートを生成する一方法を示すものです。並べ替えの指定方法が変更され、このドキュメント全体をとおして反映してあります。変更に関する詳細は、付録B 変更履歴を参照してください。
このドキュメントは、W3Cのメンバーやその他の関係者がレビューするためのW3Cワーキングドラフトです。このドキュメントはドラフトであり、更新されたり、差し替えられたり、使われなくなったりする可能性があります。参考文献としてW3Cワーキングドラフトを使用したり、「作成中」という注意書きなしでW3Cワーキングドラフトを引用したりすることは適切ではありません。このW3C ワーキングドラフトはまだ作成中であり、 W3Cメンバー による支持が得られているわけではありません。
このドキュメントは W3Cプロセスにのっとって W3C XML活動の一環として作成され、XML Queryワーキンググループ ( W3Cメンバーのみで構成)によって書かれました。 XML Queryワーキンググループのゴールは、 XML Queryワーキンググループ特権 ( W3Cメンバーだけ )において議論されます。
XML Queryワーキンググループでは、本ワーキングドラフトの内容は比較的安定していると考えており、このバージョンに対するフィードバックを期待しています。
この記述に関する特許の開示は、XML Queryワーキンググループの 特許開示ページ(http://www.w3.org/2002/08/xmlquery-IPR-statements)に記載されることがあります。
このドキュメントに関するコメントは、W3Cメーリングリスト public-qt-comments@w3.org@w3.org ( http://lists.w3.org/Archives/Public/public-qt-comments/ )までお願いいたします。
現在のW3C 勧告および他の技術ドキュメントのリストはhttp://www.w3.org/TR/にあります。
1 XML Query の記述例
1.1 記述例("XMP"):代表例
1.1.1 ドキュメント型定義(DTD)
1.1.2 サンプルデータ
1.1.3 Q5のためのDTD
1.1.4 Q5のためのサンプルデータ
1.1.5 Q9のためのDTD
1.1.6 Q9のためのデータ
1.1.7 Q10のためのDTD
1.1.8 Q10のためのデータ
1.1.9 クエリと結果
1.1.9.1 Q1
1.1.9.2 Q2
1.1.9.3 Q3
1.1.9.4 Q4
1.1.9.5 Q5
1.1.9.6 Q6
1.1.9.7 Q7
1.1.9.8 Q8
1.1.9.9 Q9
1.1.9.10 Q10
1.1.9.11 Q11
1.1.9.12 Q12
1.2 記述例("TREE"):階層構造を保持するクエリ
1.2.1 詳細
1.2.2 ドキュメント型定義(DTD)
1.2.3 サンプルデータ
1.2.4 クエリと結果
1.2.4.1 Q1
1.2.4.2 Q2
1.2.4.3 Q3
1.2.4.4 Q4
1.2.4.5 Q5
1.2.4.6 Q6
1.3 記述例("SEQ"):シーケンスにもとづくクエリ
1.3.1 詳細
1.3.2 ドキュメント型定義(DTD)
1.3.3 サンプルデータ
1.3.4 クエリと結果
1.3.4.1 Q1
1.3.4.2 Q2
1.3.4.3 Q3
1.3.4.4 Q4
1.3.4.5 Q5
1.4 記述例("R"):リレーショナルデータに対するアクセス
1.4.1 詳細
1.4.2 ドキュメント型定義(DTD)
1.4.3 サンプルデータ
1.4.4 クエリと結果
1.4.4.1 Q1
1.4.4.2 Q2
1.4.4.3 Q3
1.4.4.4 Q4
1.4.4.5 Q5
1.4.4.6 Q6
1.4.4.7 Q7
1.4.4.8 Q8
1.4.4.9 Q9
1.4.4.10 Q10
1.4.4.11 Q11
1.4.4.12 Q12
1.4.4.13 Q13
1.4.4.14 Q14
1.4.4.15 Q15
1.4.4.16 Q16
1.4.4.17 Q17
1.4.4.18 Q18
1.5 記述例("SGML"):Standard
Generalized Markup Language
1.5.1 詳細
1.5.2 ドキュメント型定義(DTD)
1.5.3 サンプルデータ
1.5.4 クエリと結果
1.5.4.1 Q1
1.5.4.2 Q2
1.5.4.3 Q3
1.5.4.4 Q4
1.5.4.5 Q5
1.5.4.6 Q6
1.5.4.7 Q7
1.5.4.8 Q8a
1.5.4.9 Q8b
1.5.4.10 Q9
1.5.4.11 Q10
1.6 記述例("STRING"):ストリング検索
1.6.1 詳細
1.6.2 ドキュメント型定義(DTD)
1.6.3 サンプルデータ
1.6.4 クエリと結果
1.6.4.1 Q1
1.6.4.2 Q2
1.6.4.3 Q4
1.6.4.4 Q5
1.7 記述例("NS"):名前空間を使用したクエリ
1.7.1 詳細
1.7.2 ドキュメント型定義(DTD)
1.7.3 サンプルデータ
1.7.4 クエリと結果
1.7.4.1 Q1
1.7.4.2 Q2
1.7.4.3 Q3
1.7.4.4 Q4
1.7.4.5 Q5
1.7.4.6 Q6
1.7.4.7 Q7
1.7.4.8 Q8
1.8 記述例("PARTS"):再帰的部分展開
1.8.1 詳細
1.8.2 ドキュメント型定義(DTD)
1.8.3 サンプルデータ
1.8.4 クエリと結果
1.8.4.1 Q1
1.9 記述例("STRONG"):強く型指定されたデータを利用するクエリ
1.9.1 詳細
1.9.2 スキーマ
1.9.3 サンプルデータ
1.9.4 クエリと結果
1.9.4.1 Q1
1.9.4.2 Q2
1.9.4.3 Q3
1.9.4.4 Q4
1.9.4.5 Q5
1.9.4.6 Q6
1.9.4.7 Q7
1.9.4.8 Q8
1.9.4.9 Q9
1.9.4.10 Q10
1.9.4.11 Q11
1.9.4.12 Q12
A 謝辞
B 変更履歴 (Non-Normative)
B.1 Nov 2002
C参照資料 (Non-Normative)
このドキュメントで紹介する記述例は、XML Query言語を適用する重要なアプリケーションを例証するために XML Queryワーキンググループが作成したものです。 記述例は特定分野のアプリケーションに焦点をあてたものであり、ドキュメント型定義(DTD)およびサンプルデータを含んでいます。“サンプルデータ”ごとに、“XQuery記述例”と“期待される結果”が示されています。各クエリには簡単な説明しか付いていないため、“期待される結果:”の記述がクエリの定義上重要な役割をはたします。そこには、期待される出力フォーマット情報も含まれています。 これらの記述例は、もともと「W3C XML Query Requirements」の一部として公表されたものです。 この時点では特定のクエリ言語を想定したものではありませんでしたが、今回はXQueryのためのソリューションとして再度公表することになりました。
開発中のパーサのテストがやり易くなるように、ここで述べる記述例のクエリを別ファイルにも使えるようにして欲しいという要望があるため、クエリは[Use Case Sample Queries]に入れました。また、XQuery仕様自体のクエリは、[XQuery Sample Queries]にあります。
記述例の中には、http://www.bn.com/bib.xmlなどの特定の名前の一つもしくは複数のフォームからの入力を前提としているものがあります。また、暗黙の(名前のない)入力ドキュメントを前提としているものもありますが、この場合には関数input()を用いてアクセスします。各記述例の入力環境は、そのDocument Type Definition (DTD)の節に示されています。
読み易くするためにクエリの出力には空白が挿入してありますが、クエリプロセッサからの出力にこのような空白が挿入されているとはかぎりません。空白は、結果の正しい表示に本質的なものとは考えないでください。
この記述例集作成の作業は、現在も継続中です。重要なアプリケーションの分野の中にも、まだ十分にカバーされていないものもあります。XML Queryワーキンググループは、作業の過程で各クエリや使用例全体を追加、削除、変更する権利を有しています。記述例で示されたクエリが、将来XML Queryワーキンググループによって作成されるXMLQuery言語に含まれる保証はありません。
本記述例は、データベースとドキュメントの両分野からの要求品物を例証するクエリ例からなっています。
本記述例のほとんどのクエリ例は、http://www.bn.com/bib.xmlという名前のDTDにもとづくもので、図書目録をあらわしています:
<!ELEMENT bib
(book* )>
<!ELEMENT book (title, (author+ | editor+ ), publisher, price )>
<!ATTLIST book year CDATA #REQUIRED >
<!ELEMENT author (last, first )>
<!ELEMENT editor (last, first, affiliation )>
<!ELEMENT title (#PCDATA )>
<!ELEMENT last (#PCDATA )>
<!ELEMENT first (#PCDATA )>
<!ELEMENT affiliation (#PCDATA )>
<!ELEMENT publisher (#PCDATA )>
<!ELEMENT price (#PCDATA )>
ここにあげたデータは、www.bn.com/bib.xmlにあります:
<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 in the Unix environment</title>
<author><last>Stevens</last><first>W.</first></author>
<publisher>Addison-Wesley</publisher>
<price>65.95</price>
</book>
<book year="2000">
<title>Data on the Web</title>
<author><last>Abiteboul</last><first>Serge</first></author>
<author><last>Buneman</last><first>Peter</first></author>
<author><last>Suciu</last><first>Dan</first></author>
<publisher>Morgan Kaufmann Publishers</publisher>
<price>39.95</price>
</book>
<book year="1999">
<title>The Economics of Technology and Content for Digital TV</title>
<editor>
<last>Gerbarg</last><first>Darcy</first>
<affiliation>CITI</affiliation>
</editor>
<publisher>Kluwer Academic Publishers</publisher>
<price>129.95</price>
</book>
</bib>
Q5では、別のデータソースにある本のレビュー情報と価格情報も利用します。次のhttp://www.amazon.com/reviews.xmlが、このDTDです:
<!ELEMENT reviews
(entry*)>
<!ELEMENT entry (title, price, review)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ELEMENT review (#PCDATA)>
http://www.amazon.com/reviews.xmlの内容は、以下のとおりです:
<reviews>
<entry>
<title>Data on the Web</title>
<price>34.95</price>
<review>
A very good discussion of semi-structured database
systems and XML.
</review>
</entry>
<entry>
<title>Advanced Programming in the Unix environment</title>
<price>65.95</price>
<review>
A clear and detailed discussion of UNIX programming.
</review>
</entry>
<entry>
<title>TCP/IP Illustrated</title>
<price>65.95</price>
<review>
One of the best books on TCP/IP.
</review>
</entry>
</reviews>
Q9は、次のDTDにもとづく”books.xml”という入力ドキュメントを使用します:
<!ELEMENT chapter
(title, section*)>
<!ELEMENT section (title, section*)>
<!ELEMENT title (#PCDATA)>
books.xmlの内容は、以下のとおりです:
<chapter>
<title>Data Model</title>
<section>
<title>Syntax For Data Model</title>
</section>
<section>
<title>XML</title>
<section>
<title>Basic Syntax</title>
</section>
<section>
<title>XML and Semistructured Data</title>
</section>
</section>
</chapter>
Q10は、次のDTDにもとづく”prices.xml”という名前の入力ドキュメントを使用します:
<!ELEMENT prices
(book*)>
<!ELEMENT book
(title, source, price)>
<!ELEMENT title
(#PCDATA)>
<!ELEMENT source
(#PCDATA)>
<!ELEMENT price
(#PCDATA)>
prices.xmlの内容は、以下のとおりです:
<prices>
<book>
<title>Advanced Programming in the Unix environment</title>
<source>www.amazon.com</source>
<price>65.95</price>
</book>
<book>
<title>Advanced Programming in the Unix environment</title>
<source>www.bn.com</source>
<price>65.95</price>
</book>
<book>
<title>TCP/IP Illustrated</title>
<source>www.amazon.com</source>
<price>65.95</price>
</book>
<book>
<title>TCP/IP Illustrated</title>
<source>www.bn.com</source>
<price>65.95</price>
</book>
<book>
<title>Data on the Web</title>
<source>www.amazon.com</source>
<price>34.95</price>
</book>
<book>
<title>Data on the Web</title>
<source>www.bn.com</source>
<price>39.95</price>
</book>
</prices>
1991年以降に Addison-Wesley から出版された本のリストを表示します。 本の情報は、出版された年(year)と表題(title)からなっています。
XQuery記述例:
<bib>
{
for $b in
document("http://www.bn.com/bib.xml")/bib/book
where $b/publisher
= "Addison-Wesley" and $b/@year > 1991
return
<book year="{ $b/@year }">
{ $b/title }
</book>
}
</bib>
期待される結果:
<bib>
<book year="1994">
<title>TCP/IP Illustrated</title>
</book>
<book year="1992">
<title>Advanced Programming in the Unix environment</title>
</book>
</bib>
表題(title)と著者(author)を1組にしたフラットなリストを作成します。 各々の組は、result という要素で囲みます。
XQueryの記述例:
<results>
{
for $b in document("http://www.bn.com/bib.xml")/bib/book,
$t in $b/title,
$a in $b/author
return
<result>
{ $t }
{ $a }
</result>
}
</results>
期待される結果:
<results>
<result>
<title>TCP/IP Illustrated</title>
<author>
<last>Stevens</last>
<first>W.</first>
</author>
</result>
<result>
<title>Advanced Programming in the Unix environment</title>
<author>
<last>Stevens</last>
<first>W.</first>
</author>
</result>
<result>
<title>Data on the Web</title>
<author>
<last>Abiteboul</last>
<first>Serge</first>
</author>
</result>
<result>
<title>Data on the Web</title>
<author>
<last>Buneman</last>
<first>Peter</first>
</author>
</result>
<result>
<title>Data on the Web</title>
<author>
<last>Suciu</last>
<first>Dan</first>
</author>
</result>
</results>
図書目録中の本の表題(title)と著者(author)のリストを作成します。 リスト全体を、result要素で囲みます。
XQuery記述例:
<results>
{
for $b in document("http://www.bn.com/bib.xml")/bib/book
return
<result>
{ $b/title }
{ $b/author }
</result>
}
</results>
期待される結果:
<results>
<result>
<title>TCP/IP Illustrated</title>
<author>
<last>Stevens</last>
<first>W.</first>
</author>
</result>
<result>
<title>Advanced Programming in the Unix environment</title>
<author>
<last>Stevens</last>
<first>W.</first>
</author>
</result>
<result>
<title>Data on the Web</title>
<author>
<last>Abiteboul</last>
<first>Serge</first>
</author>
<author>
<last>Buneman</last>
<first>Peter</first>
</author>
<author>
<last>Suciu</last>
<first>Dan</first>
</author>
</result>
<result>
<title>The Economics of Technology and Content for Digital TV</title>
</result>
</results>
図書目録中の著者ごとに、著者名(author)とその著者による全ての本の表題(title)をリストします。リストは、result要素で囲みます。
XQuery記述例:
<results>
{
for $a in distinct-values(document("http://www.bn.com/bib.xml")//author)
return
<result>
{ $a }
{
for $b in document("http://www.bn.com/bib.xml")/bib/book
where some $ba in $b/author satisfies deep-equal($ba,$a)
return
$b/title
}
</result>
}
</results>
上記のクエリでは、2つのノードが同じ構造と値を持っているかどうかを、deep-equal()を使ってテストします。distinct-value()によって、要素authorが帰される順番は定義されていません。
期待される結果:
<results>
<result>
<author>
<last>Stevens</last>
<first>W.</first>
</author>
<title>TCP/IP Illustrated</title>
<title>Advanced Programming in the Unix environment</title>
</result>
<result>
<author>
<last>Abiteboul</last>
<first>Serge</first>
</author>
<title>Data on the Web</title>
</result>
<result>
<author>
<last>Buneman</last>
<first>Peter</first>
</author>
<title>Data on the Web</title>
</result>
<result>
<author>
<last>Suciu</last>
<first>Dan</first>
</author>
<title>Data on the Web</title>
</result>
</results>
bn.comおよびamazon.comで見つかった本について、本の表題(title)とそれぞれのソースでの価格(price)をリストします。
XQuery記述例:
<books-with-prices>
{
for $b in document("http://www.bn.com/bib.xml")//book,
$a in document("http://www.amazon.com/reviews.xml")//entry
where $b/title = $a/title
return
<book-with-prices>
{ $b/title }
<price-amazon>{ $a/price/text() }</price-amazon>
<price-bn>{ $b/price/text() }</price-bn>
</book-with-prices>
}
</books-with-prices>
期待される結果:
<books-with-prices>
<book-with-prices>
<title>TCP/IP Illustrated</title>
<price-amazon>65.95</price-amazon>
<price-bn> 65.95</price-bn>
</book-with-prices>
<book-with-prices>
<title>Advanced Programming in the Unix environment</title>
<price-amazon>65.95</price-amazon>
<price-bn>65.95</price-bn>
</book-with-prices>
<book-with-prices>
<title>Data on the Web</title>
<price-amazon>34.95</price-amazon>
<price-bn>39.95</price-bn>
</book-with-prices>
</books-with-prices>
著者が1人でもいる本の表題(title)と最初の2人の著者名(author)をリストし、それ以上著者が存在する場合には"et-al"という名前の空要素をリストに追加します。
XQuery記述例:
<bib>
{
for $b in document("http://www.bn.com/bib.xml")//book
where count($b/author) > 0
return
<book>
{ $b/title }
{
for $a in $b/author[position()<=2]
return $a
}
{
if (count($b/author) > 2)
then <et-al/>
else ()
}
</book>
}
</bib>
期待される結果:
<bib>
<book>
<title>TCP/IP Illustrated</title>
<author>
<last>Stevens</last>
<first>W.</first>
</author>
</book>
<book>
<title>Advanced Programming in the Unix environment</title>
<author>
<last>Stevens</last>
<first>W.</first>
</author>
</book>
<book>
<title>Data on the Web</title>
<author>
<last>Abiteboul</last>
<first>Serge</first>
</author>
<author>
<last>Buneman</last>
<first>Peter</first>
</author>
<et-al/>
</book>
</bib>
1991年以降に Addison-Wesleyから出版された全ての本の表題(title)と出版年(year)のアルファベット順のリストを作成します。
XQuery記述例:
<bib>
{
for $b in document("http://www.bn.com/bib.xml")//book
where $b/publisher = "Addison-Wesley" and $b/@year > 1991
return
<book>
{ $b/@year }
{ $b/title }
</book>
sort by (title)
}
</bib>
期待される結果:
<bib>
<book year="1992">
<title>Advanced Programming in the Unix environment</title>
</book>
<book year="1994">
<title>TCP/IP Illustrated</title>
</book>
</bib>
要素名が文字列"or" で終わる要素中のどこかに"Suciu" という文字列を含んでいる本を見つけ、本の表題(title)と該当する要素をリストします。
XQuery記述例:
for $b in document("http://www.bn.com/bib.xml")//book
let $e := $b/*[contains(string(.),
"Suciu")
and ends-with(local-name(.), "or")]
where exists($e)
return
<book>
{ $b/title }
{ $e }
</book>
上記の記述中のstring()、local-name() 、及びends-with()は、“Functions and Operators”のドキュメントに記述されている関数です。
期待される結果:
<book>
<title>Data on the Web</title>
<author>
<last>Suciu</last>
<first>Dan</first>
</author>
</book>
“books.xml”ドキュメント中で、表題(title)の中に”XML”という単語を含む節(section)と章(chapter)を、その入れ子の深さに関係なく全て見つけます。
XQuery記述例:
<results>
{
for $t in document("books.xml")//(chapter | section)/title
where contains($t/text(), "XML")
return $t
}
</results>
期待される結果:
<results>
<title>XML</title>
<title>XML and Semistructured Data</title>
</results>
“prices.xml”ドキュメント中で本ごとの最低価格を探し、本の表題(title)をtitle属性とする"minprice"要素としてまとめます。
XQuery記述例:
<results>
{
let $doc := document("prices.xml")
for $t in distinct-values($doc//book/title)
let $p := for $x in $doc//book[title = $t]/price
return decimal($x)
return
<minprice title="{ $t/text() }">
<price>{ min($p) }</price>
</minprice>
}
</results>
期待される結果:
<results>
<minprice title="Advanced Programming in the Unix environment">
<price>65.95</price>
</minprice>
<minprice title="TCP/IP Illustrated">
<price>65.95</price>
</minprice>
<minprice title="Data on the Web">
<price>34.95</price>
</minprice>
</results>
著者(author)がいる本(book)は、表題(title)と著者(author)からなる本(book)要素を返します。編集者(editor)がいる本(book)は、表題(title)と編集者(editor)の所属(affiliation)からなる参考文献(reference)要素を返します。
XQuery記述例:
<bib>
{
for $b in document("http://www.bn.com/bib.xml")//book[author]
return
<book>
{ $b/title }
{ $b/author }
</book>
}
{
for $b in document("http://www.bn.com/bib.xml")//book[editor]
return
<reference>
{ $b/title }
{$b/editor/affiliation}
</reference>
}
</bib>
期待される結果:
<bib>
<book>
<title>TCP/IP Illustrated</title>
<author>
<last>Stevens</last>
<first>W.</first>
</author>
</book>
<book>
<title>Advanced Programming in the Unix environment</title>
<author>
<last>Stevens</last>
<first>W.</first>
</author>
</book>
<book>
<title>Data on the Web</title>
<author>
<last>Abiteboul</last>
<first>Serge</first>
</author>
<author>
<last>Buneman</last>
<first>Peter</first>
</author>
<author>
<last>Suciu</last>
<first>Dan</first>
</author>
</book>
<reference>
<title>The Economics of Technology and Content for Digital TV</title>
<affiliation>CITI</affiliation>
</reference>
</bib>
表題が異なる本のうち、著者が同一の本(異なる順番で並んでいる場合も含めて)を見つけます。
XQuery記述例:
<bib>
{
for $book1 in document("http://www.bn.com/bib.xml")//book,
$book2 in document("http://www.bn.com/bib.xml")//book
let $aut1 := for $a in $book1/author
order by $a/last,
$a/first
return $a
let $aut2 := for $a in $book2/author
order by $a/last,
$a/first
return $a
where $book1 << $book2
and not($book1/title = $book2/title)
and sequence-deep-equal($aut1, $aut2)
return
<book-pair>
{ $book1/title }
{ $book2/title }
</book-pair>
}
</bib>
期待される結果:
<bib>
<book-pair>
<title>TCP/IP Illustrated</title>
<title>Advanced Programming in the Unix environment</title>
</book-pair>
</bib>
上記の記述例では、シークエンスを比較する関数sequence-deep-equal()を使用しています。 対応する位置にある品物がすべて等しい場合に、2つのシークエンスは等しいとみなされます。シークエンスがノードのシークエンスである場合には、比較にはノードの値を使用します。
ドキュメント型のXMLには、テキストと要素が混ざり合い、しかも要素の多くはオプションであるという非常に柔軟な構造になっているものがあります。また、ドキュメント型XML は、ドキュメントごとに構造が大きく異なります。 これらのドキュメント型XML では、大抵の場合、要素の並べ方や入れ子にする仕方が非常に重要です。
XML Query言語には、オリジナルの階層を保持しながら、 ドキュメントから要素を抽出する能力が必要です。 この記述例では、本(Book)という名前の柔軟なドキュメント型XML をとおして、 この必要性を例証します。
この記述例は、”book.xml”という名前の入力ドキュメントにもとづきます。このスキーマのDTDは、”book.dtd”という名前のファイルにあります:
<!DOCTYPE book
[
<!ELEMENT
book (title, author+, section+)>
<!ELEMENT
title (#PCDATA)>
<!ELEMENT
author (#PCDATA)>
<!ELEMENT
section (title, (p | figure | section)* )>
<!ATTLIST
section
id ID
#IMPLIED
difficulty CDATA #IMPLIED>
<!ELEMENT
p (#PCDATA)>
<!ELEMENT
figure (title, image)>
<!ATTLIST
figure
width CDATA #REQUIRED
height CDATA #REQUIRED >
<!ELEMENT
image EMPTY>
<!ATTLIST
image
source CDATA #REQUIRED >
]>
この記述例のクエリは、次のサンプルデータにもとづいています。
<?xml version="1.0"?>
<!DOCTYPE book
SYSTEM "book.dtd">
<book>
<title>Data
on the Web</title>
<author>Serge
Abiteboul</author>
<author>Peter
Buneman</author>
<author>Dan
Suciu</author>
<section
id="intro" difficulty="easy" >
<title>Introduction</title>
<p>Text ... </p>
<section>
<title>Audience</title>
<p>Text ... </p>
</section>
<section>
<title>Web Data and the Two Cultures</title>
<p>Text ... </p>
<figure height="400" width="400">
<title>Traditional client/server architecture</title>
<image source="csarch.gif"/>
</figure>
<p>Text ... </p>
</section>
</section>
<section
id="syntax" difficulty="medium" >
<title>A Syntax For Data</title>
<p>Text ... </p>
<figure height="200" width="500">
<title>Graph representations of structures</title>
<image source="graphs.gif"/>
</figure>
<p>Text ... </p>
<section>
<title>Base Types</title>
<p>Text ... </p>
</section>
<section>
<title>Representing Relational Databases</title>
<p>Text ... </p>
<figure height="250" width="400">
<title>Examples of Relations</title>
<image source="relations.gif"/>
</figure>
</section>
<section>
<title>Representing Object Databases</title>
<p>Text ... </p>
</section>
</section>
</book>
すべての節の名前をリストして、Book1の内容を入れ子テーブルとして作成します。<section>要素に属性が付随している場合には、その属性を保持します。
XQuery記述例:
define function
toc( element $e )
returns element*
{
let $n :=
local-name( $e )
return
if ($n = "section")
then
<section>
{ $e/@* }
{ toc($e/*) }
</section>
else if ($n = "title")
then $e
else ()
}
<toc>
{
toc( document("book1.xml")/book )
}
</toc>
期待される結果:
<toc>
<section id="intro" difficulty="easy">
<title>Introduction</title>
<section>
<title>Audience</title>
</section>
<section>
<title>Web Data and the Two Cultures</title>
</section>
</section>
<section id="syntax" difficulty="medium">
<title>A Syntax For Data</title>
<section>
<title>Base Types</title>
</section>
<section>
<title>Representing Relational Databases</title>
</section>
<section>
<title>Representing Object Databases</title>
</section>
</section>
</toc>
すべての図(figure)とその名前(title)をリストして、Book1の図をフラットにリストします。<figure>要素に属性が付随している場合には、その属性を保持します。
XQuery記述例:
<figlist>
{
for $f in document("book1.xml")//figure
return
<figure>
{ $f/@* }
{ $f/title }
</figure>
}
</figlist>
期待される結果:
<figlist>
<figure height="400" width="400">
<title>Traditional client/server architecture</title>
</figure>
<figure height="200" width="500">
<title>Graph representations of structures</title>
</figure>
<figure height="250" width ="400">
<title>Examples of Relations</title>
</figure>
</figlist>
Book1中の節(section)と図(figure)の数を数えます。
XQuery記述例:
<section_count>{
count(document("book.xml")//section) }</section_count>,
<figure_count>{
count(document("book.xml")//figure) }</figure_count>
期待される結果:
<section_count>7</section_count>
<figure_count>3</figure_count>
Book1中には、最上位の節(section)がいくつあるか数えます。
XQuery記述例:
<top_section_count>
{
count(document("book.xml")/book/section)
}
</top_section_count>
期待される結果:
<top_section_count>2</top_section_count>
Book1の節(section)要素のフラットなリストを作成します。オリジナルの属性の代わりに、各節(section)要素は、節名(title)と節に直接含まれている図(figure)の数を、2つの属性とします。
XQuery記述例:
<section_list>
{
for $s in document("book.xml")//section
let $f := $s/figure
return
<section title="{ $s/title/text() }" figcount="{ count($f)
}"/>
}
</section_list>
期待される結果:
<section_list>
<section title="Introduction" figcount="0"/>
<section title="Audience" figcount="0"/>
<section title="Web Data and the Two Cultures" figcount="1"/>
<section title="A Syntax For Data" figcount="1"/>
<section title="Base Types" figcount="0"/>
<section title="Representing Relational Databases" figcount="1"/>
<section title="Representing Object Databases" figcount="0"/>
</section_list>
Book1の節(section)要素の入れ子リストを作成します。オリジナルの属性および階層構造は保持します。各節(section)要素の内部には、節名(title)と節(section)に直接含まれる図(figure)の数を要素として持ちます。
XQuery記述例:
define function
section_summary($s as element) as element
{
<section>
{ $s/@* }
{ $s/title }
<figcount>{ count($s/figure) }</figcount>
{
for $ss in $s/section
return section_summary($ss)
}
</section>
}
<toc>
{
for $s in document("book.xml")/book/section
return section_summary($s)
}
</toc>
期待される結果:
<toc>
<section id="intro" difficulty="easy">
<title>Introduction</title>
<figcount>0</figcount>
<section>
<title>Audience</title>
<figcount>0</figcount>
</section>
<section>
<title>Web Data and the Two Cultures</title>
<figcount>1</figcount>
</section>
</section>
<section id="syntax" difficulty="medium">
<title>A Syntax For Data</title>
<figcount>1</figcount>
<section>
<title>Base Types</title>
<figcount>0</figcount>
</section>
<section>
<title>Representing Relational Databases</title>
<figcount>1</figcount>
</section>
<section>
<title>Representing Object Databases</title>
<figcount>0</figcount>
</section>
</section>
</toc>
この利用例は、ドキュメントに現われる要素であるシークエンスにもとづいたクエリを例証します。
シークエンスは従来のデータベースシステムやオブジェクトシステムのほとんどでは重要ではありませんが、 構造化されたドキュメントにおいては非常に重要になりえます。 この利用例では、医療報告書にもとづく一連のクエリを示します。
この記述例は、“HL7患者記録アーキテクチャー”による医療報告書にもとづいています。ここでは、クエリを理解するために必要なものだけを使用するようにして、DTDを簡略化してあります。
<!DOCTYPE report
[
<!ELEMENT
report (section*)>
<!ELEMENT
section (section.title, section.content)>
<!ELEMENT
section.title (#PCDATA )>
<!ELEMENT
section.content (#PCDATA | anesthesia | prep
| incision | action | observation )*>
<!ELEMENT
anesthesia (#PCDATA)>
<!ELEMENT
prep ( (#PCDATA | action)* )>
<!ELEMENT
incision ( (#PCDATA | geography | instrument)* )>
<!ELEMENT
action ( (#PCDATA | instrument )* )>
<!ELEMENT
observation (#PCDATA)>
<!ELEMENT
geography (#PCDATA)>
<!ELEMENT
instrument (#PCDATA)>
]>
この記述例のクエリは、次のサンプルデータによっています。
<report>
<section>
<section.title>Procedure</section.title>
<section.content>
The patient was taken to the operating room where she was placed
in supine position and
<anesthesia>induced under general anesthesia.</anesthesia>
<prep>
<action>A Foley catheter was placed to decompress the bladder</action>
and the abdomen was then prepped and draped in sterile fashion.
</prep>
<incision>
A curvilinear incision was made
<geography>in the midline immediately infraumbilical</geography>
and the subcutaneous tissue was divided
<instrument>using electrocautery.</instrument>
</incision>
The fascia was identified and
<action>#2 0 Maxon stay sutures were placed on each side of the
midline.
</action>
<incision>
The fascia was divided using
<instrument>electrocautery</instrument>
and the peritoneum was entered.
</incision>
<observation>The small bowel was identified.</observation>
and
<action>
the
<instrument>Hasson trocar</instrument>
was placed under direct visualization.
</action>
<action>
The
<instrument>trocar</instrument>
was secured to the fascia using the stay sutures.
</action>
</section.content>
</section>
</report>
Report1の手続き(Procedure)節(section)で、2回目の切開(incision)で使用された器具(Instruments)を調べます。
XQuery記述例:
for $s in document("report1.xml")//section[section.title
= "Procedure"]
return ($s//incision)[2]/instrument
期待される結果:
<instrument>electrocautery</instrument>
Report1の手続き(Procedure)節(section)で、使用された最初の2つの器具(instrument)は何か調べます。
XQuery記述例:
for $s in document("report1.xml")//section[section.title
= "Procedure"]
return ($s//instrument)[position()<=2]
期待される結果:
<instrument>using
electrocautery.</instrument>
<instrument>electrocautery</instrument>
Report1で、2回目の切開(incision)後に行われた最初の2つの処置(action)で使用された器具を調べます。
XQuery記述例:
let $i2 := (document("report1.xml")//incision)[2]
for $a in (document("report1.xml")//action)[.
>> $i2][position()<=2]
return $a//instrument
期待される結果:
<instrument>Hasson
trocar</instrument>
<instrument>trocar</instrument>
Report1で、1回目の切開(incision)の前に麻酔(Anesthesia)要素が1つもないという”手続き(Procedure)”節(section)を探します。
XQuery記述例:
for $p in document("report1.xml")//section[section.title
= "Procedure"]
where not(some $a
in $p//anesthesia satisfies
$a << ($p//incision)[1] )
return $p
期待される結果:
(幸運なことに、Q4を満たす節(section)はありません。)
Report1で、最初の切開(incision)と2回目の切開(incision) の間に何が起こったかを調べます。
XQuery記述例:
define function
precedes($a as node, $b as node) as boolean
{
$a << $b
and
empty($a//node() intersect $b)
}
define function
follows($a as node, $b as node) as boolean
{
$a >> $b
and
empty($b//node() intersect $a)
}
<critical_sequence>
{
let $proc
:= document("report1.xml")//section[section.title="Procedure"][1]
for $n in
$proc//node()
where follows($n,
($proc//incision)[1])
and precedes($n, ($proc//incision)[2])
return $n
}
</critical_sequence>
恐らくより効率的ですが、それほど読みやすくない別の記述法を以下に示します:
<critical_sequence>
{
let $proc
:= document("report1.xml")//section[section.title="Procedure"][1],
$i1 := ($proc//incision)[1],
$i2 := ($proc//incision)[2]
for $n in
$proc//node() except $i1//node()
where $n
>> $i1 and $n << $i2
return $n
}
</critical_sequence>
期待される結果:
<critical_sequence>
The fascia was identified and
<action>#2 0 Maxon stay sutures were placed on each side of the
midline.</action>#2 0 Maxon stay sutures were placed on each side
of the midline.
</critical_sequence>
XML Query言語の重要な使用方法の1つとして、リレーショナルデータベースに 格納されたデータに対するアクセスがあります。ここでは、リレーショナルデータベースに格納されたデータにアクセスする 一例を示します。
リレーショナルデータベースシステムでは、各テーブル(リレーション)がXMLドキュメントの形態をとるビューを表しているかもしれません。データベーステーブルをXMLドキュメントとして表す方法の1つに、テーブル自身をドキュメント要素とし、テーブル内の各row(タプル)が入れ子構造をなすように表わす方法があります。タプル要素内では、各column(カラム)が入れ子構造を構成します。null値を許されているcolumn(カラム)はオプションの要素として表され、存在しない要素はnull値によって表わされます。
ここでは、例としてオンラインオークションによって利用されるリレーショナルデータベースを考えてみましょう。オークションでは、登録ユーザの情報を格納しているUSERSテーブルを利用します。 各ユーザはユニークなユーザIDで識別され、これにもとづいて品物を売りに出したり、入札を行ったりします。ITEMS テーブルは、現在競売中もしくは最近競売にかけられたばかりの品物のリストで、品物の提供者のユーザIDが格納されています。BIDSテーブルには、入札者のユーザIDと入札にかけられた品物番号をキーとした全入札記録が格納されています。
オンラインオークションで使用される3つのテーブルは以下のとおりです。カッコ内はcolumn(カラム)名を表しています。
USERS ( USERID,
NAME, RATING )
ITEMS ( ITEMNO,
DESCRIPTION, OFFERED_BY, START_DATE, END_DATE, RESERVE_PRICE )
BIDS ( USERID, ITEMNO,
BID, BID_DATE )
この記述例は、users.xml、items.xmlおよびbids.xmlという名前の 3つの入力ドキュメントを使用します。 各ドキュメントは、上述のリレーショナルデータベースにおける各々のテーブルを表わします。これらのドキュメントは、DTDは以下のとおりです:
<!DOCTYPE users
[
<!ELEMENT
users (user_tuple*)>
<!ELEMENT
user_tuple (userid, name, rating?)>
<!ELEMENT
userid (#PCDATA)>
<!ELEMENT
name (#PCDATA)>
<!ELEMENT
rating (#PCDATA)>
]>
<!DOCTYPE items
[
<!ELEMENT
items (item_tuple*)>
<!ELEMENT
item_tuple (itemno, description, offered_by,
start_date?, end_date?, reserve_price? )>
<!ELEMENT
itemno (#PCDATA)>
<!ELEMENT
description (#PCDATA)>
<!ELEMENT
offered_by (#PCDATA)>
<!ELEMENT
start_date (#PCDATA)>
<!ELEMENT
end_date (#PCDATA)>
<!ELEMENT
reserve_price (#PCDATA)>
]>
<!DOCTYPE bids
[
<!ELEMENT
bids (bid_tuple*)>
<!ELEMENT
bid_tuple (userid, itemno, bid, bid_date)>
<!ELEMENT
userid (#PCDATA)>
<!ELEMENT
itemno (#PCDATA)>
<!ELEMENT
bid (#PCDATA)>
<!ELEMENT
bid_date (#PCDATA)>
]>
インスタンスのXMLフォーマットを示すための簡略化したデータです:
<items>
<item_tuple>
<itemno>1001</itemno>
<description>Red Bicycle</description>
<offered_by>U01</offered_by>
<start_date>1999-01-05</start_date>
<end_date>1999-01-20</end_date>
<reserve_price>40</reserve_price>
</item_tuple>
<!-- !!!
Snip !!! -->
<users>
<user_tuple>
<userid>U01</userid>
<name>Tom Jones</name>
<rating>B</rating>
</user_tuple>
<!-- !!!
Snip !!! -->
<bids>
<bid_tuple>
<userid>U02</userid>
<itemno>1001</itemno>
<bid>35</bid>
<bid_date>1999-01-07</bid_date>
</bid_tuple>
<bid_tuple>
<!-- !!!
Snip !!! -->
完全なデータセットについては、次のテーブルを参照して下さい:
| USERS |
||
| USERID |
NAME |
RATING |
| U01 |
Tom Jones |
B |
| U02 |
Mary Doe |
A |
| U03 |
Dee Linquent |
D |
| U04 |
Roger Smith |
C |
| U05 |
Jack Sprat |
B |
| U06 |
Rip Van Winkle |
B |
| ITEMS |
|||||
| ITEMNO |
DESCRIPTION |
OFFERED_BY |
START_DATE |
END_DATE |
RESERVE_PRICE |
| 1001 |
Red Bicycle |
U01 |
1999-01-05 |
1999-01-20 |
40 |
| 1002 |
Motorcycle |
U02 |
1999-02-11 |
1999-03-15 |
500 |
| 1003 |
Old Bicycle |
U02 |
1999-01-10 |
1999-02-20 |
25 |
| 1004 |
Tricycle |
U01 |
1999-02-25 |
1999-03-08 |
15 |
| 1005 |
Tennis Racket |
U03 |
1999-03-19 |
1999-04-30 |
20 |
| 1006 |
Helicopter |
U03 |
1999-05-05 |
1999-05-25 |
50000 |
| 1007 |
Racing Bicycle |
U04 |
1999-01-20 |
1999-02-20 |
200 |
| 1008 |
Broken Bicycle |
U01 |
1999-02-05 |
1999-03-06 |
25 |
| BIDS |
|||
| USERID |
ITEMNO |
BID |
BID_DATE |
| U02 |
1001 |
35 |
1999-01-07 |
| U04 |
1001 |
40 |
1999-01-08 |
| U02 |
1001 |
45 |
1999-01-11 |
| U04 |
1001 |
50 |
1999-01-13 |
| U02 |
1001 |
55 |
1999-01-15 |
| U01 |
1002 |
400 |
1999-02-14 |
| U02 |
1002 |
600 |
1999-02-16 |
| U03 |
1002 |
800 |
1999-02-17 |
| U04 |
1002 |
1000 |
1999-02-25 |
| U02 |
1002 |
1200 |
1999-03-02 |
| U04 |
1003 |
15 |
1999-01-22 |
| U05 |
1003 |
20 |
1999-02-03 |
| U01 |
1004 |
40 |
1999-03-05 |
| U03 |
1007 |
175 |
1999-01-25 |
| U05 |
1007 |
200 |
1999-02-08 |
| U04 |
1007 |
225 |
1999-02-12 |
以下は、1999年2月1日にクエリを行ったと仮定した場合の結果です。
現在行われているオークションのすべての自転車の品物番号(itemno)と詳細(description)を、品物番号順にリストします。
XQuery記述例:
<result>
{
for $i in document("items.xml")//item_tuple
where $i/start_date <= current-date()
and $i/end_date >= current-date()
and contains($i/description, "Bicycle")
order by $1/itemno
return
<item_tuple>
{ $i/itemno }
{ $i/description }
</item_tuple>
}
</result>
期待される結果:
<result>
<item_tuple>
<itemno>1003</itemno>
<description>Old Bicycle</description>
</item_tuple>
<item_tuple>
<itemno>1007</itemno>
<description>Racing Bicycle</description>
</item_tuple>
</result>
上記のクエリは、item_tupleという名前の要素を返しますが、その定義はDTD のitem_tupleの定義とは一致していません。
すべての自転車について、品物番号(itemno)、詳細(description)および(もしあれば)最高入札価格(bid)を、品物番号順にリストします。
XQuery記述例:
<result>
{
for $i in document("items.xml")//item_tuple
let $b := document("bids.xml")//bid_tuple[itemno = $i/itemno]
where contains($i/description, "Bicycle")
order by $1/itemno
return
<item_tuple>
{ $i/itemno }
{ $i/description }
<high_bid>{ max(for $z in $b/bid return decimal($z)) }</high_bid>
</item_tuple>
}
</result>
期待される結果:
<result>
<item_tuple>
<itemno>1001</itemno>
<description>Red Bicycle</description>
<high_bid>55.0</high_bid>
</item_tuple><item_tuple>
<itemno>1003</itemno>
<description>Old Bicycle</description>
<high_bid>20.0</high_bid>
</item_tuple><item_tuple>
<itemno>1007</itemno>
<description>Racing Bicycle</description>
<high_bid>225.0</high_bid>
</item_tuple><item_tuple>
<itemno>1008</itemno>
<description>Broken Bicycle</description>
<high_bid></high_bid>
</item_tuple>
</result>
信用度の格付け(rating)が”C”より悪い(アルファベット順 でより大きな値を持つ)ユーザが、1000以上の最低競売価格(reserve_price)を品物につけたケースを見つけます。
XQuery記述例:
<result>
{
for $u in document("users.xml")//user_tuple
for $i in document("items.xml")//item_tuple
where $u/rating > "C"
and $i/reserve_price > 1000
and $i/offered_by = $u/userid
return
<warning>
{ $u/name }
{ $u/rating }
{ $i/description }
{ $i/reserve_price }
</warning>
}
</result>
期待される結果:
<result>
<warning>
<name>Dee Linquent</name>
<rating>D</rating>
<description>Helicopter</description>
<reserve_price>50000</reserve_price>
</warning>
</result>
入札価格(bid)がまだついていない品物の品物番号(itemno)と詳細(description)をリストします。
XQuery記述例:
<result>
{
for $i in document("items.xml")//item_tuple
where empty(document("bids.xml")//bid_tuple[itemno = $i/itemno])
return
<no_bid_item>
{ $i/itemno }
{ $i/description }
</no_bid_item>
}
</result>
期待される結果:
<result>
<no_bid_item>
&