このドキュメントは、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>
<itemno>1005</itemno>
<description>Tennis Racket</description>
</no_bid_item>
<no_bid_item>
<itemno>1006</itemno>
<description>Helicopter</description>
</no_bid_item>
<no_bid_item>
<itemno>1008</itemno>
<description>Broken Bicycle</description>
</no_bid_item>
</result>
入札価格(bid)がついていて、トム・ジョーンズ(Tom Jones)から 売買の申し込みがあった自転車(bicycle)の、品物番号(itemno)、詳細(description)、最高入札価格(bid)、 最高入札価格をつけた人の名前 を、品物番号(itemno)順にリストします。
XQuery記述例:
<result>
{
for $seller in document("users.xml")//user_tuple,
$buyer in document("users.xml")//user_tuple,
$item in document("items.xml")//item_tuple,
$highbid in document("bids.xml")//bid_tuple
where $seller/name = "Tom Jones"
and $seller/userid = $item/offered_by
and contains($item/description , "Bicycle")
and $item/itemno = $highbid/itemno
and $highbid/userid = $buyer/userid
and $highbid/bid = max(
for $x in document("bids.xml")//bid_tuple
[itemno = $item/itemno]/bid
return decimal($x)
)
order by ($item/itemno)
return
<jones_bike>
{ $item/itemno }
{ $item/description }
<high_bid>{ $highbid/bid }</high_bid>
<high_bidder>{ $buyer/name }</high_bidder>
</jones_bike>
}
</result>
次の記述例では、リストの順序性に意味がないことをクエリプロセッサーに通知する関数unordered
をfor句の中で使用しています。 つまり、これはタプルが任意の順序で生成されることを意味します。
これによって、よりよい最適化が可能になります。
別のXQuery記述例:
<result>
{
for $seller in unordered document("users.xml")//user_tuple,
$buyer in unordered document("users.xml")//user_tuple,
$item in unordered document("items.xml")//item_tuple,
$highbid in document("bids.xml")//bid_tuple
where $seller/name = "Tom Jones"
and $seller/userid = $item/offered_by
and contains($item/description , "Bicycle")
and $item/itemno = $highbid/itemno
and $highbid/userid = $buyer/userid
and $highbid/bid = max(for $x in unordered document("bids.xml")//bid_tuple
[itemno = $item/itemno]/bid
return decimal(data($x)))
order by $item/itemno
return
<jones_bike>
{ $item/itemno }
{ $item/description }
<high_bid>{ $highbid/bid }</high_bid>
<high_bidder>{ $buyer/name }</high_bidder>
</jones_bike>
}
</result>
期待される結果:
<result>
<jones_bike>
<itemno>1001</itemno>
<description>Red Bicycle</description>
<high_bid>
<bid>55</bid>
</high_bid>
<high_bidder>
<name>Mary Doe</name>
</high_bidder>
</jones_bike>
</result>
最高入札価格(bid)が最低競売価格(reserve_price)の2倍以上ある品物の、品物番号(itemno)、詳細(description)、最低競売価格(reserve_price)、最高入札価格(bid)をリストにします。
XQuery記述例:
<result>
{
for $item in document("items.xml")//item_tuple
let $b := document("bids.xml")//bid_tuple[itemno = $item/itemno]
let $z := max(for $x in $b/bid return decimal($x))
where $item/reserve_price * 2 < $z
return
<successful_item>
{ $item/itemno }
{ $item/description }
{ $item/reserve_price }
<high_bid>{$z }</high_bid>
</successful_item>
}
</result>
期待される結果:
<result>
<successful_item>
<itemno>1002</itemno>
<description>Motorcycle</description>
<reserve_price>500</reserve_price>
<high_bid>1200.0</high_bid>
</successful_item>
<successful_item>
<itemno>1004</itemno>
<description>Tricycle</description>
<reserve_price>15</reserve_price>
<high_bid>40.0</high_bid>
</successful_item>
</result>
これまで自転車(Bicycle)か三輪車(Tricycle)に対してつけられた最高入札価格(bid)を求めます。
XQuery記述例:
let $allbikes :=
document("items.xml")//item_tuple
[contains(description, "Bicycle")
or contains(description, "Tricycle")]
let $bikebids :=
document("bids.xml")//bid_tuple[itemno = $allbikes/itemno]
return
<high_bid>
{
max(for $x in $bikebids/bid return decimal($x))
}
</high_bid>
期待される結果:
<high_bid>225.0</high_bid>
1999年3月に取引が完了した品物がいくつあるのか調べます。
XQuery記述例:
let $item := document("items.xml")//item_tuple
[end_date
>= date("1999-03-01") and end_date <= date("1999-03-31")]
return
<item_count>
{
count($item)
}
</item_count>
期待される結果:
<item_count>3</item_count>
データが利用できる範囲で、1999年に競売にかけられた品物数を、 月ごとに順番にリストします。
XQuery記述例:
<result>
{
let $end_dates := document("items.xml")//item_tuple/end_date
for $m in distinct-values(for $e in $end_dates
return get-month-from-date($e))
let $item := document("items.xml")
//item_tuple[get-year-from-date(end_date) = 1999
and get-month-from-date(end_date) = $m]
order by $m
return
<monthly_result>
<month>{ $m }</month>
<item_count>{ count($item) }</item_count>
</monthly_result>
}
</result>
期待される結果:
<result>
<monthly_result>
<month>01</month>
<item_count>1</item_count>
</monthly_result>
<monthly_result>
<month>02</month>
<item_count>2</item_count>
</monthly_result>
<monthly_result>
<month>03</month>
<item_count>3</item_count>
</monthly_result>
<monthly_result>
<month>04</month>
<item_count>1</item_count>
</monthly_result>
<monthly_result>
<month>05</month>
<item_count>1</item_count>
</monthly_result>
</result>
入札価格(bid)がついた品物(item)の品物番号(itemno)、最高入札価格(bid)、最高入札価格をつけた人の名前を品物番号(itemno)順にリストにします。
XQuery記述例:
<result>
{
for $highbid in document("bids.xml")//bid_tuple,
$user in document("users.xml")//user_tuple
where $user/userid = $highbid/userid
and $highbid/bid = max(for $x in document("bids.xml")//bid_tuple
[itemno=$highbid/itemno]/bid return decimal($x))
order by $highbid/itemno
return
<high_bid>
{ $highbid/itemno }
{ $highbid/bid }
<bidder>{ $user/name/text() }</bidder>
</high_bid>
}
</result>
期待される結果:
<result>
<high_bid>
<itemno>1001</itemno>
<bid>55</bid>
<bidder>Mary Doe</bidder>
</high_bid>
<high_bid>
<itemno>1002</itemno>
<bid>1200</bid>
<bidder>Mary Doe</bidder>
</high_bid>
<high_bid>
<itemno>1003</itemno>
<bid>20</bid>
<bidder>Jack Sprat</bidder>
</high_bid>
<high_bid>
<itemno>1004</itemno>
<bid>40</bid>
<bidder>Tom Jones</bidder>
</high_bid>
<high_bid>
<itemno>1007</itemno>
<bid>225</bid>
<bidder>Roger Smith</bidder>
</high_bid>
</result>
これまで記録されたうちの最高入札価格(bid)をつけた品物(item)の品物番号(itemno)、品物の詳細(description)と、その時の入札価格(bid)をリストにします。
XQuery記述例:
let $highbid :=
max(for $x in document("bids.xml")//bid_tuple/bid
return decimal($x))
return
<result>
{
for $item in document("items.xml")//item_tuple,
$b in document("bids.xml")//bid_tuple[itemno = $item/itemno]
where $b/bid = $highbid
return
<expensive_item>
{ $item/itemno }
{ $item/description }
<high_bid>{ $highbid }</high_bid>
</expensive_item>
}
</result>
期待される結果:
<result>
<expensive_item>
<itemno>1002</itemno>
<description>Motorcycle</description>
<high_bid>1200.0</high_bid>
</expensive_item>
</result>
これまで入札数が一番多かった品物(item)の品物番号(itemno)、品物の詳細(description)、及び入札数をリストします。
XQuery記述例:
define function
bid_summary ()
{
for $i in distinct-values(document("bids.xml")//itemno)
let $b := document("bids.xml")//bid_tuple[itemno = $i]
return
<bid_count>
{ $i }
<nbids>{ count($b) }</nbids>
</bid_count>
}
<result>
{
let $bid_counts := bid_summary(),
$maxbids := max(for $x in $bid_counts/nbids return decimal($x)),
$maxitemnos := $bid_counts[nbids = $maxbids]
for $item in document("items.xml")//item_tuple,
$bc in $bid_counts
where $bc/nbids = $maxbids and $item/itemno = $bc/itemno
return
<popular_item>
{ $item/itemno }
{ $item/description }
<bid_count>{ $bc/nbids/text() }</bid_count>
</popular_item>
}
</result>
期待される結果:
<result>
<popular_item>
<itemno>1001</itemno>
<description>Red Bicycle</description>
<bid_count>5</bid_count>
</popular_item>
<popular_item>
<itemno>1002</itemno>
<description>Motorcycle</description>
<bid_count>5</bid_count>
</popular_item>
</result>
1回でも入札(bid)したことのあるユーザ(user)の、ユーザ番号(userid)、名前(name)、入札(bid)回数、 及び入札価格(bid)の平均値を、ユーザ番号(userid)順にリストします。
XQuery記述例:
<result>
{
for $uid in distinct-values(document("bids.xml")//userid),
$u in document("users.xml")//user_tuple[userid = $uid]
let $b := document("bids.xml")//bid_tuple[userid = $uid]
order by $u/userid
return
<bidder>
{ $u/userid }
{ $u/name }
<bidcount>{ count($b) }</bidcount>
<avgbid>{ avg(for $x in $b/bid return decimal($x)) }</avgbid>
</bidder>
}
</result>
期待される結果:
<result>
<bidder>
<userid>U01</userid>
<name>Tom Jones</name>
<bidcount>2</bidcount>
<avgbid>220.0</avgbid>
</bidder>
<bidder>
<userid>U02</userid>
<name>Mary Doe</name>
<bidcount>5</bidcount>
<avgbid>387.0</avgbid>
</bidder>
<bidder>
<userid>U03</userid>
<name>Dee Linquent</name>
<bidcount>2</bidcount>
<avgbid>487.5</avgbid>
</bidder>
<bidder>
<userid>U04</userid>
<name>Roger Smith</name>
<bidcount>5</bidcount>
<avgbid>266.0</avgbid>
</bidder>
<bidder>
<userid>U05</userid>
<name>Jack Sprat</name>
<bidcount>2</bidcount>
<avgbid>110.0</avgbid>
</bidder>
</result>
3回以上入札価格(bid)がつけられた品物(item)の、品物番号(itemno)と入札価格(bid)の平均値を、入札価格(bid)の平均値順に 降順(descending)でリストします。
XQuery記述例:
<result>
{
for $i in distinct-values(document("bids.xml")//itemno)
let $b := document("bids.xml")//bid_tuple[itemno = $i]
let $avgbid := decimal(avg(for $x in $s/bid return decimal($x)))
where count($b)
>= 3
order by $avgbid descending
return
<popular_item>
{ $i }
<avgbid>{ $avgbid }</avgbid>
</popular_item>
}
</result>
期待される結果:
<result>
<popular_item>
<itemno>1002</itemno>
<avgbid>800.0</avgbid>
</popular_item>
<popular_item>
<itemno>1007</itemno>
<avgbid>200.0</avgbid>
</popular_item>
<popular_item>
<itemno>1001</itemno>
<avgbid>45.0</avgbid>
</popular_item>
</result>
100ドル以上の入札価格(bid)を2つ以上つけたユーザ(user)の名前(name)をリストします。
XQuery記述例:
<result>
{
for $u in document("users.xml")//user_tuple
let $b := document("bids.xml")//bid_tuple[userid=$u/userid and
bid>=100]
where count($b) > 1
return
<big_spender>{ $u/name/text() }</big_spender>
}
</result>
期待される結果:
<result>
<big_spender>Mary Doe</big_spender>
<big_spender>Dee Linquent</big_spender>
<big_spender>Roger Smith</big_spender>
</result>
登録されている全ユーザ(user)を、 ユーザ番号(userid)順にリストします。 この時、ユーザごとに、ユーザ番号(userid)、名前(name)、 及びユーザが活発(記録上で少なくとも1回入札(bid)を行っている)なのか、活発でない(記録上で1回も入札(bid)を行っていない)のかの目安を表示します。
XQuery記述例:
<result>
{
for $u in document("users.xml")//user_tuple
let $b := document("bids.xml")//bid_tuple[userid = $u/userid]
order by $u/userid
return
<user>
{ $u/userid }
{ $u/name }
{
if (empty($b))
then <status>inactive</status>
else <status>active</status>
}
</user>
}
</result>
期待される結果:
<result>
<user>
<userid>U01</userid>
<name>Tom Jones</name>
<status>active</status>
</user>
<user>
<userid>U02</userid>
<name>Mary Doe</name>
<status>active</status>
</user>
<user>
<userid>U03</userid>
<name>Dee Linquent</name>
<status>active</status>
</user>
<user>
<userid>U04</userid>
<name>Roger Smith</name>
<status>active</status>
</user>
<user>
<userid>U05</userid>
<name>Jack Sprat</name>
<status>active</status>
</user>
<user>
<userid>U06</userid>
<name>Rip Van Winkle</name>
<status>inactive</status>
</user>
</result>
全ての品物(item)に対して入札(bid)を行った人がもしいれば、 そのユーザ(user)の名前(name)をリストします。
XQuery記述例:
<frequent_bidder>
{
for $u in document("users.xml")//user_tuple
where
every $item in document("items.xml")//item_tuple satisfies
some $b in document("bids.xml")//bid_tuple satisfies
($item/itemno = $b/itemno and $u/userid = $b/userid)
return
$u/name
}
</frequent_bidder>
期待される結果:
(Q17の条件を満たすユーザはいません。)
全てのユーザ(user)を、名前(name)のアルファベット順にリストします。このとき、各ユーザ(user)によって入札(bid)された全品物(item)(もしあれば)の詳細(description)を表示します。詳細(description)は、アルファベット順に並べます。
XQuery記述例:
<result>
{
for $u in document("users.xml")//user_tuple
return
<user>
{ $u/name }
{
for $b in distinct-values(document("bids.xml")//bid_tuple
[userid = $u/userid]/itemno),
for $i in document("items.xml")//item_tuple[itemno = $b]
let $descr := $i/description/text()
order by $descr
return
<bid_on_item>{ $descr }</bid_on_item>
}
</user>
}
</result>
期待される結果:
<result>
<user>
<name>Dee Linquent</name>
<bid_on_item>Motorcycle</bid_on_item>
<bid_on_item>Racing Bicycle</bid_on_item>
</user>
<user>
<name>Jack Sprat</name>
<bid_on_item>Old Bicycle</bid_on_item>
<bid_on_item>Racing Bicycle</bid_on_item>
</user>
<user>
<name>Mary Doe</name>
<bid_on_item>Motorcycle</bid_on_item>
<bid_on_item>Red Bicycle</bid_on_item>
</user>
<user>
<name>Rip Van Winkle</name>
</user>
<user>
<name>Roger Smith</name>
<bid_on_item>Motorcycle</bid_on_item>
<bid_on_item>Old Bicycle</bid_on_item>
<bid_on_item>Racing Bicycle</bid_on_item>
<bid_on_item>Red Bicycle</bid_on_item>
</user>
<user>
<name>Tom Jones</name>
<bid_on_item>Motorcycle</bid_on_item>
<bid_on_item>Tricycle</bid_on_item>
</user>
</result>
このドキュメントとクエリの例は、もともと1992年のStandard Generalized Markup Language(SGML)の会議のために作成されたものです。理解しやすいように、ドキュメント型定義(DTD)とドキュメント例はSGML からXML に変換してあります。
この例は、暗黙の(名前のない)入力データセットにもとづいています。DTDは、次のようになります。
<!NOTATION
cgm PUBLIC "Computer Graphics Metafile">
<!NOTATION
ccitt PUBLIC "CCITT group 4 raster">
<!ENTITY
% text "(#PCDATA | emph)*">
<!ENTITY
infoflow SYSTEM "infoflow.ccitt" NDATA ccitt>
<!ENTITY
tagexamp SYSTEM "tagexamp.cgm" NDATA cgm>
<!ELEMENT
report (title, chapter+)>
<!ELEMENT
title %text;>
<!ELEMENT
chapter (title, intro?, section*)>
<!ATTLIST
chapter
shorttitle CDATA #IMPLIED>
<!ELEMENT
intro (para | graphic)+>
<!ELEMENT
section (title, intro?, topic*)>
<!ATTLIST
section
shorttitle CDATA #IMPLIED
sectid ID #IMPLIED>
<!ELEMENT
topic (title, (para | graphic)+)>
<!ATTLIST
topic
shorttitle CDATA #IMPLIED
topicid ID #IMPLIED>
<!ELEMENT
para (#PCDATA | emph | xref)*>
<!ATTLIST
para
security (u | c | s | ts) "u">
<!ELEMENT
emph %text;>
<!ELEMENT
graphic EMPTY>
<!ATTLIST
graphic
graphname ENTITY #REQUIRED>
<!ELEMENT
xref EMPTY>
<!ATTLIST
xref
xrefid IDREF #IMPLIED>
この記述例中のクエリは、次のサンプルデータにもとづいています。 クエリ結果を特定しやすいように、データには行番号をつけてあります。
0: <!DOCTYPE
report SYSTEM "report.dtd">
1: <report>
2: <title>Getting
started with SGML</title>
3: <chapter>
4: <title>The
business challenge</title>
5: <intro>
6: <para>With
the ever-changing and growing global market, companies and
7: large organizations
are searching for ways to become more viable and
8: competitive.
Downsizing and other cost-cutting measures demand more
9: efficient
use of corporate resources. One very important resource is
10: an organization's
information.</para>
11: <para>As
part of the move toward integrated information management,
12: whole industries
are developing and implementing standards for
13: exchanging technical
information. This report describes how one such
14: standard, the
Standard Generalized Markup Language (SGML), works as
15: part of an overall
information management strategy.</para>
16: <graphic
graphname="infoflow"/></intro></chapter>
17: <chapter>
18: <title>Getting
to know SGML</title>
19: <intro>
20: <para>While
SGML is a fairly recent technology, the use of
21: <emph>markup</emph>
in computer-generated documents has existed for a
22: while.</para></intro>
23: <section
shorttitle="What is markup?">
24: <title>What
is markup, or everything you always wanted to know about
25: document preparation
but were afraid to ask?</title>
26: <intro>
27: <para>Markup
is everything in a document that is not content. The
28: traditional
meaning of markup is the manual <emph>marking</emph> up
29: of typewritten
text to give instructions for a typesetter or
30: compositor about
how to fit the text on a page and what typefaces to
31: use. This kind of markup is known as <emph>procedural markup</emph>.</para></intro>
32: <topic topicid="top1">
33: <title>Procedural
markup</title>
34: <para>Most
electronic publishing systems today use some form of
35: procedural markup.
Procedural markup codes are good for one
36: presentation
of the information.</para></topic>
37: <topic topicid="top2">
38: <title>Generic
markup</title>
39: <para>Generic
markup (also known as descriptive markup) describes the
40: <emph>purpose</emph>
of the text in a document. A basic concept of
41: generic markup
is that the content of a document must be separate from
42: the style. Generic
markup allows for multiple presentations of the
43: information.</para></topic>
44: <topic topicid="top3">
45: <title>Drawbacks
of procedural markup</title>
46: <para>Industries
involved in technical documentation increasingly
47: prefer generic
over procedural markup schemes. When a company changes
48: software or
hardware systems, enormous data translation tasks arise,
49: often resulting
in errors.</para></topic></section>
50: <section
shorttitle="What is SGML?">
51: <title>What
<emph>is</emph> SGML in the grand scheme of the universe,
anyway?</title>
52: <intro>
53: <para>SGML
defines a strict markup scheme with a syntax for defining
54: document data
elements and an overall framework for marking up
55: documents.</para>
56: <para>SGML
can describe and create documents that are not dependent on
57: any hardware,
software, formatter, or operating system. Since SGML documents
58: conform to an
international standard, they are portable.</para></intro></section>
59: <section
shorttitle="How does SGML work?">
60: <title>How
is SGML and would you recommend it to your grandmother?</title>
61: <intro>
62: <para>You
can break a typical document into three layers: structure,
63: content, and
style. SGML works by separating these three aspects and
64: deals mainly
with the relationship between structure and content.</para></intro>
65: <topic topicid="top4">
66: <title>Structure</title>
67: <para>At
the heart of an SGML application is a file called the DTD, or
68: Document Type
Definition. The DTD sets up the structure of a document,
69: much like a
database schema describes the types of information it
70: handles.</para>
71: <para>A
database schema also defines the relationships between the
72: various types
of data. Similarly, a DTD specifies <emph>rules</emph>
73: to help ensure
documents have a consistent, logical structure.</para></topic>
74: <topic topicid="top5">
75: <title>Content</title>
76: <para>Content
is the information itself. The method for identifying
77: the information
and its meaning within this framework is called
78: <emph>tagging</emph>.
Tagging must
79: conform to the
rules established in the DTD (see <xref xrefid="top4"/>).</para>
80: <graphic
graphname="tagexamp"/></topic>
81: <topic topicid="top6">
82: <title>Style</title>
83: <para>SGML
does not standardize style or other processing methods for
84: information
stored in SGML.</para></topic></section></chapter>
85: <chapter>
86: <title>Resources</title>
87: <section>
88: <title>Conferences,
tutorials, and training</title>
89: <intro>
90: <para>The
Graphic Communications Association has been
91: instrumental
in the development of SGML. GCA provides conferences,
92: tutorials, newsletters,
and publication sales for both members and
93: non-members.</para>
94: <para security="c">Exiled
members of the former Soviet Union's secret
95: police, the
KGB, have infiltrated the upper ranks of the GCA and are
96: planning the
Final Revolution as soon as DSSSL is completed.</para>
97: </intro>
98: </section>
99: </chapter>
100:</report>
報告書(report)中の全てのパラグラフ(paragraph) の位置を特定します。("report"要素内にある全ての"para"要素)
XQuery記述例:
<result>
{
input()//report//para
}
</result>
期待される結果:
開始タグが、行番号6, 11, 20, 27, 34, 39, 46, 53, 56, 62, 67, 71, 76, 83, 90, 94にある要素。
序論(introduction)の中の全てのパラグラフの位置を特定します。("intro"要素内にある全ての"para"要素)
XQuery記述例:
<result>
{
input()//intro/para
}
</result>
期待される結果:
開始タグが、行番号6, 11, 20, 27, 53, 56, 62, 90, 94にある要素
序論(introduction)がない章(chapter)にある節(section)の序論(introduction)中にある全てのパラグラフ(paragraph)の位置を特定します。("chapter"要素内にある"section"要素の内の、"intro"要素内にある全ての"para"要素。"intro"要素を含む"chapter"要素は除く。)
XQuery記述例:
<result>
{
for $c in input()//chapter
where empty($c/intro)
return $c/section/intro/para
}
</result>
期待される結果:
開始タグが、行番号90, 94にある要素
第2章(chapter)の第3節(section)にある第2パラグラフ(paragraph)の位置を特定します。("report"中の2番目の"chapter"要素内の3番目の"section"要素の内の2番目の"para"要素。)
XQuery記述例:
<result>
{
(((input()//chapter)[2]//section)[3]//para)[2]
}
</result>
期待される結果:
開始タグが、行番号67にある要素
機密扱いのパラグラフ(paragraph)の位置を特定します。 ("security"属性が値"c"であるすべての"para"要素)
XQuery記述例:
<result>
{
input()//para[@security = "c"]
}
</result>
期待される結果:
開始タグが、行番号94にある要素
すべての節(section)の略称(shorttitle)をリストします。 (全ての"section"要素にある"shorttitle"属性の値を、それぞれ新しい要素の値として表現。)
XQuery記述例:
<result>
{
for $s in input()//section/@shorttitle
return <stitle>{ $s }</stitle>
}
</result>
期待される結果:
開始タグが、行番号23, 50, 59にある要素
全ての序論(introduction)の最初のパラグラフ(paragraph)の最初の文字をリストします。("intro"要素内の最初の"para"要素の内容 [文字としての内容も要素としての内容も同様] の内の最初の文字。)
XQuery記述例:
<result>
{
for $i in input()//intro/para[1]
return
<first_letter>{ substring(string($i), 1, 1) }</first_letter>
}
</result>
期待される結果:
行番号6, 20, 27, 53, 62, 90にある開始タグの直後の文字
"is SGML"という文字列を含む表題(title)の節(section)をすべてリストします。("is SGML"という連続した文字列をその内容に持つ"title"要素を持っている全ての"section"要素)。 その文字列は、配下要素によって分断されていても構いません。
XQuery記述例:
<result>
{
input()//section[contains(string(.//title), "is SGML")]
}
</result>
期待される結果:
開始タグが、行番号50, 59にある要素
(Q8a)と同じですが、その文字列は配下要素によって分断されていないものだけをリストします。
XQuery記述例:
<result>
{
input()//section[contains(.//title/text(), "is SGML")]
}
</result>
期待される結果:
開始タグが、行番号59 にある要素
報告書(report)の中のどこかにある相互参照(xref)によって関係づけられたトピック(topic)を全てリストします。("topicid"属性を持ち、その属性値が任意の"xref"要素の"xrefid"属性の値と同じである 全ての"topic"要素")
XQuery記述例:
<result>
{
for $id in input()//xref/@xrefid
return input()//topic[@topicid = $id]
}
</result>
期待される結果:
開始タグが、行番号65にある要素
"xrefid"属性の値が"top4"である相互参照("xref")要素のもっとも直前にある表題(title)を見つけます。(ドキュメントの順番で各要素を並べたとき、 この"xref"要素の前にあり、かつ最後に現れた"title"要素)
XQuery記述例:
<result>
{
let $x := input()//xref[@xrefid = "top4"],
$t := input()//title[. << $x]
return $t[last()]
}
</result>
期待される結果:
79行目のxrefが対応するので、行番号75に開始タグがある要素
この記述例は、企業評価やPR、合併、買収などのデータを含む一連のニュースドキュメントをもとにしています。ある企業に関するニュースドキュメント内のテキストサーチのやり方をいくつかと、クエリの結果を企業評価やニュースの内容とマッチングさせる方法をいくつか示します。
この例では、ノードもしくは空の文字列が含まれていないかをテストするために、関数contains
が使用されています。
もちろん、関数full-textを使用すればより強力なサーチが可能ですが、現段階では“Functions and Operators draft”に関数full-textは含まれていません。
この記述例の暗黙の(名前のない)入力データセットのDTD は次のとおりです。
<!ELEMENT company
(name, ticker_symbol?, description?,
business_code, partners?, competitors?)>
<!ELEMENT name
(#PCDATA)>
<!ELEMENT ticker_symbol
(#PCDATA)>
<!ELEMENT description
(#PCDATA)>
<!ELEMENT business_code
(#PCDATA)>
<!ELEMENT partners
(partner+)>
<!ELEMENT partner
(#PCDATA)>
<!ELEMENT competitors
(competitor+)>
<!ELEMENT competitor
(#PCDATA)>
<!ELEMENT news
(news_item*)>
<!ELEMENT news_item
(title, content, date, author?, news_agent)>
<!ELEMENT title
(#PCDATA)>
<!ELEMENT content
(par | figure)+ >
<!ELEMENT date
(#PCDATA)>
<!ELEMENT author
(#PCDATA)>
<!ELEMENT news_agent
(#PCDATA)>
<!ELEMENT par
(#PCDATA | quote | footnote)*>
<!ELEMENT quote
(#PCDATA)>
<!ELEMENT footnote
(#PCDATA)>
<!ELEMENT figure
(title, image)>
<!ELEMENT image
EMPTY>
<!ATTLIST image
source CDATA #REQUIRED >
この記述例のクエリは、関数input()をとおして得られた以下の入力データに対して行われます。
<?xml version="1.0"
encoding="ISO-8859-1"?>
<news>
<news_item>
<title>
Gorilla Corporation acquires YouNameItWeIntegrateIt.com </title>
<content>
<par> Today, Gorilla Corporation announced that it will purchase
YouNameItWeIntegrateIt.com. The shares of
YouNameItWeIntegrateIt.com dropped $3.00 as a result of this
announcement.
</par>
<par> As a result of this acquisition, the CEO of
YouNameItWeIntegrateIt.com Bill Smarts resigned. He did not
announce what he will do next. Sources close to
YouNameItWeIntegrateIt.com hint that Bill
Smarts might be
taking a position in Foobar Corporation.
</par>
<par>YouNameItWeIntegrateIt.com is a leading systems integrator
that enables <quote>brick and mortar</quote> companies to
have a presence on the web.
</par>
</content>
<date>1-20-2000</date>
<author>Mark
Davis</author>
<news_agent>News
Online</news_agent>
</news_item>
<news_item>
<title>Foobar
Corporation releases its new line of Foo products
today</title>
<content>
<par> Foobar Corporation releases the 20.9 version of its Foo
products. The new version of Foo products solve known
performance problems which existed in 20.8 line and
increases the speed of Foo based products tenfold. It also
allows wireless clients to be connected to the Foobar
servers.
</par>
<par> The President of Foobar Corporation announced that they
were proud to release 20.9 version of Foo products and
they will upgrade existing customers <footnote>where
service agreements exist</footnote>
promptly. TheAppCompany Inc. immediately announced that it
will release the new version of its products to utilize
the 20.9 architecture within the next three months.
</par>
<figure>
<title>Presidents of Foobar Corporation and TheAppCompany
Inc. Shake Hands</title> <image source="handshake.jpg"/>
</figure>
</content>
<date>1-20-2000</date>
<news_agent>Foobar
Corporation</news_agent>
</news_item>
<news_item>
<title>Foobar Corporation is suing Gorilla Corporation for
patent
infringement </title>
<content>
<par> In surprising developments today, Foobar Corporation
announced that it is suing Gorilla Corporation for patent
infringement. The patents that were mentioned as part of the
lawsuit are considered to be the basis of Foobar
Corporation's <quote>Wireless Foo</quote> line of products.
</par>
<par>The tension between Foobar and Gorilla Corporations has
been increasing ever since the Gorilla Corporation acquired
more than 40 engineers who have left Foobar Corporation,
TheAppCompany Inc. and YouNameItWeIntegrateIt.com over the
past 3 months. The engineers who have left the Foobar
corporation and its partners were rumored to be working on
the next generation of server products and applications which
will directly compete with Foobar's Foo 20.9 servers. Most of
the engineers have relocated to Hawaii where the Gorilla
Corporation's server development is located.
</par>
</content>
<date>1-20-2000</date>
<news_agent>Reliable
News Corporation</news_agent>
</news_item>
</news>
さらに、ファイル”company-data.xml”にはその企業の提携企業と競合企業がリストされています。
<?xml version="1.0"
encoding="ISO-8859-1"?>
<!DOCTYPE company
SYSTEM "company.dtd">
<company>
<name>Foobar
Corporation</name>
<ticker_symbol>FOO</ticker_symbol>
<description>Foobar
Corporation is a maker of Foo(TM) and
Foobar(TM) products and a leading software company with a 300
Billion dollar revenue in 1999. It is located in Alaska.
</description>
<business_code>Software</business_code>
<partners>
<partner>YouNameItWeIntegrateIt.com</partner>
<partner>TheAppCompany Inc.</partner>
</partners>
<competitors>
<competitor>Gorilla Corporation</competitor>
</competitors>
</company>
表題に"Foobar Corporation"という文字列を含む全てのニュース項目を見つけます。
XQuery記述例:
input()//news_item/title[contains(./text(), "Foobar Corporation")]
期待される結果:
<title>Foobar
Corporation releases its new line of Foo
products today</title>
<title>Foobar
Corporation is suing Gorilla Corporation for patent
infringement </title>
Foobar Corporationと1つ以上の提携企業が、ひとつのパラグラフもしくは表題内にいっしょに掲載されているニュース項目をみつけ、ニュース項目の表題と日付をリストします。
XQuery記述例:
define function
partners($company as xs:string) as element*
{
let $c := document("company-data.xml")//company[name = $company]
return $c//partner
}
let $foobar_partners
:= partners("Foobar Corporation")
for $item in input()//news_item
where
some $t in
$item//title satisfies
(contains($t/text(), "Foobar Corporation")
and some $partner in $foobar_partners satisfies
contains($t/text(), $partner/text()))
or some $par
in $item//par satisfies
(contains(string($par),
"Foobar Corporation")
and some $partner in $foobar_partners satisfies
contains(string($par), $partner/text()))
return
<news_item>
{ $item/title }
{ $item/date }
</news_item>
期待される結果:
<news_item>
<title> Gorilla Corporation acquires YouNameItWeIntegrateIt.com
</title>
<date>1-20-2000</date>
</news_item>
<news_item>
<title>Foobar Corporation releases its new line of Foo products
today</title>
<date>1-20-2000</date>
</news_item>
<news_item>
<title>Foobar Corporation is suing Gorilla Corporation for patent
infringement </title>
<date>1-20-2000</date>
</news_item>
企業とその提携企業の内の1社が同時に掲載されているニュース項目の内、その企業自身によらないニュース項目を見つけます。
XQuery記述例:
define function
partners($company as xs:string) as element*
{
let $c := document("company-data.xml")//company[name = $company]
return $c//partner
}
for $item in input()//news_item,
$c in document("company-data.xml")//company
let $partners :=
partners($c/name)
where contains(string($item),
$c/name)
and some
$p in $partners satisfies
contains(string($item), $p) and $item/news_agent != $c/name
return
$item
期待される結果: 以下の表題(title)を含む要素:
· Gorilla CorporationがYouNameItWeIntegrateIt.comを買収
· Foobar Corporationが、特許侵害でGorilla Corporationを提訴
Gorilla Corporationに関するニュース項目ごとに、項目サマリー(item summary)要素を作成します。項目サマリーには、表題、日付、最初のパラグラフがピリオドで区切られて入っています。ニュース項目のどこかに、該当する企業名が入っているニュース項目はすべて含みます。
XQuery記述例:
for $item in input()//news_item
where contains(string($item/content),
"Gorilla Corporation")
return
<item_summary>
{ $item/title/text() }.
{ $item/date/text() }.
{ string(($item//par)[1]) }
</item_summary>
期待される結果: (読み易い空白を挿入してあります。)
<item_summary>
Gorilla
Corporation acquires YouNameItWeIntegrateIt.com. 1-20-2000.
Today,
Gorilla Corporation announced that it will purchase
YouNameItWeIntegrateIt.com.
The shares of YouNameItWeIntegrateIt.com
dropped
$3.00 as a result of this announcement.
</item_summary>
<item_summary>
Foobar
Corporation is suing Gorilla Corporation for patent infringement.
1-20-2000.
In surprising developments today, Foobar Corporation announced
that
it is suing Gorilla Corporation for patent infringement. The patents
that
were mentioned as part of the lawsuit are considered to be the
basis
of Foobar Corporation's <quote>Wireless Foo</quote> line of
products.
</item_summary>
この記述例では、名前空間つきノード名に対する様々なクエリを行います。
この記述例がもとにしているシナリオは、 中立の立場に立つ調停者が、クライアントに代わって、 公開のオークションを行うというものです。 クライアントがこの仮想のサービスを利用する理由というのは、 名前を伏せるためであったり、 より安全な保険をかけるためであったり、 同時に1つ以上のマーケットに参加するためであったりします。 名前空間の以下の面が、この記述例によって示されます。
· 異なるソースからなるXMLデータが組み合わされた場合の、構文のあいまいさの解決
· XLinksやXMLスキーマのようなあらかじめ定義されているモジュールの再利用
· Dublin Coreのようなグローバル分類スキーマのサポート
サンプルデータは2レコードからなり、W3C XML Schemaのスキーマコンポジションであらかじめ定義されたスキーマと、モジュール分割された名前空間、そしてスキーマを作り出し参照を表現するためにXLinkを使います。 個々のレコードは、実行中のオークションを表しています。 このレコードには、競売人(つまり、会社の信用格付けシステム)と特定の物品(ジャズのレコード)が、 オークションでは知られたデータ(開始終了時間など)が フレームワークに組み込まれていて、名前空間を使ってこの3つの語彙を識別しています。
注意していただきたいのは、名前空間で限定された名前の突合せを行う前に、名前空間の接頭辞が名前空間のURIに 対して解決されていないといけないということです。 名前空間を提供するために、文字の接頭辞を使うのには 差し支えがあります。 更にいうと、名前空間の宣言する方法には、 いつくかの可能な方法があるということです。 つまり、名前空間の処理は、XML Information Setによって 処理された名前空間に対して行わればならいないということで、 XMLのテキスト表現に対してではないということです。
DTDには名前空間との完全な互換性がなく 同じ名前空間内のノードの同等性を表現できませんが、 異なった名前空間プロキシを使えば可能です。 このドキュメントの後のバージョンは、ここにXML Schemaがここに追加されるべきです。
この記述例は、暗黙の(名前なしの)入力データセットを前提としてます。
<?xml version="1.0"
encoding="ISO-8859-1"?>
<ma:AuctionWatchList
xmlns:ma="http://www.example.com/AuctionWatch"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:anyzone="http://www.example.com/auctioneers#anyzone"
xmlns:eachbay="http://www.example.com/auctioneers#eachbay"
xmlns:yabadoo="http://www.example.com/auctioneers#yabadoo"
>
<!-- ________________________________________________________________________________
-->
<ma:Auction anyzone:ID="0321K372910">
<ma:AuctionHomepage
xlink:type="simple"
xlink:href="http://www.example.com/item/0321K372910"
/>
<ma:Schedule>
<ma:Open xmlns:dt="http://www.w3.org/2001/XMLSchema"
dt:type="timeInstant">2000-03-21:07:41:34-05:00</ma:Open>
<ma:Close xmlns:dt="http://www.w3.org/2001/XMLSchema"
dt:type="timeInstant">2000-03-23:07:41:34-05:00</ma:Close>
</ma:Schedule>
<ma:Price>
<ma:Start ma:currency="USD">3.00</ma:Start>
<ma:Current ma:currency="USD">10.00</ma:Current>
<ma:Number_of_Bids>5</ma:Number_of_Bids>
</ma:Price>
<ma:Trading_Partners>
<ma:High_Bidder>
<eachbay:ID>RecordsRUs</eachbay:ID>
<eachbay:PositiveComments>231</eachbay:PositiveComments>
<eachbay:NeutralComments>2</eachbay:NeutralComments>
<eachbay:NegativeComments>5</eachbay:NegativeComments>
<ma:MemberInfoPage
xlink:type="simple"
xlink:href="http://auction.eachbay.com/members?get=RecordsRUs"
xlink:role="ma:MemberInfoPage"
/>
</ma:High_Bidder>
<ma:Seller>
<anyzone:ID>VintageRecordFreak</anyzone:ID>
<anyzone:Member_Since>October 1999</anyzone:Member_Since>
<anyzone:Rating>5</anyzone:Rating>
<ma:MemberInfoPage
xlink:type="simple"
xlink:href="http://auction.anyzone.com/members/VintageRecordFreak"
xlink:role="ma:MemberInfoPage"
/>
</ma:Seller>
</ma:Trading_Partners>
<ma:Details>
<record xmlns="http://www.example.org/music/records">
<artist>Miles Davis</artist>
<title>In a Silent Way</title>
<recorded>1969</recorded>
<label>Columbia Records</label>
<remark>
With Miles Davis (trumpet), Herbie Hancock (Electric
Piano), Chick Corea (Electric Piano), Wayne Shorter
(Tenor Sax), Josef Zawinul (Electric Piano &
Organ), John McLaughlin (Guitar), and Tony Williams
(Drums). The liner notes were written by Frank Glenn,
and the record is in fine condition.
</remark>
</record>
</ma:Details>
</ma:Auction>
<!-- ________________________________________________________________________________
-->
<ma:Auction yabadoo:ID="13143816">
<ma:AuctionHomepage
xlink:type="simple"
xlink:href="http://auctions.yabadoo.com/auction/13143816"
/>
<ma:Schedule>
<ma:Open xmlns:dt="http://www.w3.org/2001/XMLSchema"
dt:type="timeInstant">2000-03-19:17:03:00-04:00</ma:Open>
<ma:Close xmlns:dt="http://www.w3.org/2001/XMLSchema"
dt:type="timeInstant">2000-03-29:17:03:00-04:00</ma:Close>
</ma:Schedule>
<ma:Price>
<ma:Start ma:currency="USD">3.00</ma:Start>
<ma:Current ma:currency="USD">3.00</ma:Current>
<ma:Number_of_Bids>0</ma:Number_of_Bids>
</ma:Price>
<ma:Trading_Partners>
<ma:High_Bidder>
<eachbay:ID>VintageRecordFreak</eachbay:ID>
<eachbay:PositiveComments>232</eachbay:PositiveComments>
<eachbay:NeutralComments>0</eachbay:NeutralComments>
<eachbay:NegativeComments>0</eachbay:NegativeComments>
<ma:MemberInfoPage
xlink:type="simple"
xlink:href="http://auction.eachbay.com/showRating/user=VintageRecordFreak"
xlink:role="ma:MemberInfoPage"
/>
</ma:High_Bidder>
<ma:Seller xmlns:seller="http://www.example.com/auctioneers#eachbay">
<seller:ID>StarsOn45</seller:ID>
<seller:PositiveComments>80</seller:PositiveComments>
<seller:NeutralComments>1</seller:NeutralComments>
<seller:NegativeComments>2</seller:NegativeComments>
<ma:MemberInfoPage
xlink:type="simple"
xlink:href="http://auction.eachbay.com/showRating/user=StarsOn45"
xlink:role="ma:MemberInfoPage"
/>
</ma:Seller>
</ma:Trading_Partners>
<ma:Details>
<record xmlns="http://www.example.org/music/records">
<artist>Wynton Marsalis</artist>
<title>Think of One ...</title>
<recorded>1983</recorded>
<label>Columbia Records</label>
<remark xml:lang="en"> Columbia Records 12" 33-1/3
rpm LP,
#FC-38641, Stereo. The record is still clean and shiny
and looks unplayed (looks like NM condition). The
cover has very light surface and edge wear.
</remark>
<remark xml:lang="de"> Columbia Records 12" 33-1/3
rpm LP,
#FC-38641, Stereo. Die Platte ist noch immer sauber
und gl舅zend und sieht ungespielt aus
(NM Zustand). Das Cover hat leichte Abnutzungen an
Oberfl臘he und Ecken.
</remark>
</record>
</ma:Details>
</ma:Auction>
</ma:AuctionWatchList>
サンプルデータで使われている名前空間(namespace-uri)を一意なリスト(ns)にします。
XQuery記述例:
<Q1>
{
for $n in distinct-values(
for $i in (input()//* | input()//@*)
return namespace-uri($i)
)
return <ns>{$n}</ns>
}
</Q1>
期待される結果:
<Q1>
</ns>http://www.example.com/AuctionWatch</ns>
</ns>http://www.example.com/auctioneers#anyzone</ns>
</ns>http://www.w3.org/1999/xlink</ns>
</ns>http://www.w3.org/2001/XMLSchema</ns>
</ns>http://www.example.com/auctioneers#eachbay</ns>
</ns>http://www.example.org/music/records</ns>
</ns>http://www.example.com/auctioneers#yabadoo</ns>
</ns>xml</ns>
</Q1>
競売に出されているレコード盤から、表題(music:title)をセレクトします。
XQuery記述例:
declare namespace
music = "http://www.example.org/music/records"
<Q2>
{
input()//music:title
}
</Q2>
期待される結果:
<Q2 xmlns:music="http://www.example.org/music/records">
<music:title>In
a Silent Way</music:title>
<music:title>Think
of One ...</music:title>
</Q2>
"XML Schema: Part2"のデータ型(dt:)を使っている要素をセレクトします。
XQuery記述例:
declare namespace
dt = "http://www.w3.org/2001/XMLSchema"
<Q3>
{
input()//*[@dt:*]
}
</Q3>
(名前空間が定義されているものと一致する 属性を持つ全ノードを見つけます。)
期待される結果:
<Q3 xmlns:dt="http://www.w3.org/2001/XMLSchema">
<ma:Open
xmlns:ma="http://www.example.com/AuctionWatch"
dt:type="timeInstant">2000-03-21:07:41:34-05:00</ma:Open>
<ma:Close
xmlns:ma="http://www.example.com/AuctionWatch"
dt:type="timeInstant">2000-03-23:07:41:34-05:00</ma:Close>
<ma:Open
xmlns:ma="http://www.example.com/AuctionWatch"
dt:type="timeInstant">2000-03-19:17:03:00-04:00</ma:Open>
<ma:Close
xmlns:ma="http://www.example.com/AuctionWatch"
dt:type="timeInstant">2000-03-29:17:03:00-04:00</ma:Close>
</Q3>
ドキュメント内の全XLkinksの目的URI(xlink:herf)をリスト(ns)します。
XQuery記述例:
declare namespace
xlink = "http://www.w3.org/1999/xlink"
<Q4>
{
for $hr in input()//@xlink:href
return <ns>{ $hr }</ns>
}
</Q4>
($hrをherf:と名づけられた属性ノードにバインドして、 属性ノードをその値から取り出した文字列に連結します。)
期待される結果:
<Q4 xmlns:xlink="http://www.w3.org/1999/xlink">
<ns xlink:href="http://www.example.com/item/0321K372910"/>
<ns xlink:href="http://auction.eachbay.com/members?get=RecordsRUs"/>
<ns xlink:href="http://auction.anyzone.com/members/VintageRecordFreak"/>
<ns xlink:href="http://auctions.yabadoo.com/auction/13143816"/>
<ns xlink:href="http://auction.eachbay.com/showRating/user=VintageRecordFreak"/>
<ns xlink:href="http://auction.eachbay.com/showRating/user=StarsOn45"/>
</Q4>
論評(music:remark)がドイツ語(xml:lang="de")でなされている レコード盤をすべてセレクトします。
XQuery記述例:
declare namespace
music = "http://www.example.org/music/records"
<Q5>
{
input()//music:record[music:remark/@xml:lang = "de"]
}
</Q5>
期待される結果:
<Q5 xmlns:music="http://www.example.org/music/records">
<music:record>
<music:artist>Wynton Marsalis</music:artist>
<music:title>Think of One ...</music:title>
<music:recorded>1983</music:recorded>
<music:label>Columbia Records</music:label>
<music:remark xml:lang="en"> Columbia Records 12"
33-1/3 rpm LP,
#FC-38641, Stereo. The record is still clean and shiny and
looks unplayed (looks like NM condition). The cover has very
light surface and edge wear.
</music:remark>
<music:remark xml:lang="de"> Columbia Records 12"
33-1/3 rpm LP,
#FC-38641, Stereo. Die Platte ist noch immer sauber und
gl舅zend und sieht ungespielt aus (NM Zustand). Das
Cover hat
leichte
Abnutzungen an Oberfl臘he und Ecken.
</music:remark>
</music:record>
</Q5>
現在見ているAnyZoneオークション(ma:Auction)の終了時間(ma:close)をセレクトします。
XQuery記述例:
declare namespace
ma = "http://www.example.com/AuctionWatch"
declare namespace
anyzone = "http://www.example.com/auctioneers#anyzone"
<Q6>
{
input()//ma:Auction[@anyzone:ID]/ma:Schedule/ma:Close
}
</Q6>
期待される結果:
<Q6 xmlns:ma="http://www.example.com/AuctionWatch">
<ma:Close
xmlns:dt="http://www.w3.org/2001/XMLSchema" dt:type="timeInstant">2000-03-23:07:41:34-05:00</ma:Close>
</Q6>
売り手(ma:seller)と最高値入札者(ma:High_Bidder)が、 同じ競売人である全オークション(ma:Auction)の ホームページ(namespace_uri)をセレクトします。
XQuery記述例:
declare namespace
ma = "http://www.example.com/AuctionWatch"
<Q7>
{
for $a in document("data/ns-data.xml")//ma:Auction
let $seller_id := $a/ma:Trading_Partners/ma:Seller/*:ID,
$buyer_id := $a/ma:Trading_Partners/ma:High_Bidder/*:ID
where namespace-uri($seller_id) = namespace-uri($buyer_id)
return
$a/ma:AuctionHomepage
}
</Q7>
期待される結果:
<Q7 xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ma="http://www.example.com/AuctionWatch" >
<ma:AuctionHomepage
xlink:type="simple"
xlink:href="http://auctions.yabadoo.com/auction/13143816" />
</Q7>
消極的な発言(NegativeComments)をしていない トレーダ(ma:Seller)と最高値入札者(High_Bidder)) をすべてセレクトします。
XQuery記述例:
declare namespace
ma = "http://www.example.com/AuctionWatch"
<Q8>
{
for $s in input()//ma:Trading_Partners/(ma:Seller | ma:High_Bidder)
where $s/*:NegativeComments = 0
return $s
}
</Q8>
期待される結果:
<Q8 xmlns:ma="http://www.example.com/AuctionWatch">
<ma:High_Bidder xmlns:eachbay="http://www.example.com/auctioneers#eachbay"
xmlns:xlink="http://www.w3.org/1999/xlink">
<eachbay:ID>VintageRecordFreak</eachbay:ID>
<eachbay:PositiveComments>232</eachbay:PositiveComments>
<eachbay:NeutralComments>0</eachbay:NeutralComments>
<eachbay:NegativeComments>0</eachbay:NegativeComments>
<ma:MemberInfoPage xlink:type="simple"
xlink:href="http://auction.eachbay.com/showRating/user=VintageRecordFreak"
xlink:role="ma:MemberInfoPage"/>
</ma:High_Bidder>
</Q8>
この記述例では、再帰クエリがどのように使われるかを明らかにします。データベースに蓄積されたフラットな構造から、任意の深さを持つ階層構造のドキュメントを構築します。
この記述例は、"部分展開"データベースを元にしています。 このデータベースが保持している情報は、部分が他の部分でどのように 使われるかというものです。
この記述例の入力は、"フラットな"ドキュメントで、それぞれのドキュメントの部分は、partIDと名前属性からなる部分(part)要素によって示されています。 個々の部分は、より大きな部分の一部であったり、 そうでなかったりします。 より大きな部分に含まれている場合は、そのより大きな部分のpartIDが部分構成(part of)要素に含まれます。 この入力ドキュメントはリレーショナルデータベースから 導き出されていて、それぞれの部分はテーブルのrowとして 格納されています。partIDがプライマリキーとなっていて、部分構成(part of)が、partIDを参照する外部キーとなっています。
この記述例のクエリは、外部キーに基づいた"フラットな"部分の展開の表現を階層表現に変換するもので、格納されている部分をドキュメントの構造に従ったものに変換します。
入力データセットのDTDは、つぎのとおりです:
<!DOCTYPE partlist
[
<!ELEMENT partlist (part*)>
<!ELEMENT part EMPTY>
<!ATTLIST part
partid CDATA #REQUIRED
partof CDATA #IMPLIED
name CDATA #REQUIRED>
]>
partID
とpartOF
属性が
順にtypeID、IDREFであったとしても、 リレーショナルデータベースから そのまま取り出してきたものでしょうから、 このスキーマでは文字型データとして扱います。
個々のpartOF
属性は、 ちょうど1つのpartID
に一致します。
partOF
属性を持たない部分は、 他の部分に含まれません。
出力データのDTD は、つぎのとおりです:
<!DOCTYPE parttree
[
<!ELEMENT parttree (part*)>
<!ELEMENT part (part*)>
<!ATTLIST part
partid CDATA #REQUIRED
name CDATA #REQUIRED>
]>
<?xml version="1.0"
encoding="ISO-8859-1"?>
<partlist>
<part
partid="0" name="car"/>
<part
partid="1" partof="0" name="engine"/>
<part
partid="2" partof="0" name="door"/>
<part
partid="3" partof="1" name="piston"/>
<part
partid="4" partof="2" name="window"/>
<part
partid="5" partof="2" name="lock"/>
<part
partid="10" name="skateboard"/>
<part
partid="11" partof="10" name="board"/>
<part
partid="12" partof="10" name="wheel"/>
<part
partid="20" name="canoe"/>
</partlist>
サンプルのドキュメントを、"partlist"フォーマットから "parttree"フォーマットに変換します(定義については、DTDセクションをご覧ください)。変換後のドキュメントでは、 部分が、ある部分(part)要素が別の要素に格納された構造として表されています。 他の部分の一部とはならない部分は、 出力ドキュメントの内では、トップレベルの要素として分離されています。
XQuery記述例:
define function
one_level ($p as element) as element
{
<part partid="{ $p/@partid }"
name="{ $p/@name }" >
{
for $s in document("partlist.xml")//part
where $s/@partof = $p/@partid
return one_level($s)
}
</part>
}
<parttree>
{
for $p in document("partlist.xml")//part[empty(@partof)]
return one_level($p)
}
</parttree>
期待される結果:
<parttree>
<part partid="0" name="car">
<part partid="1" name="engine">
<part partid="3" name="piston"/>
</part>
<part partid="2" name="door">
<part partid="4" name="window"/>
<part partid="5" name="lock"/>
</part>
</part>
<part partid="10" name="skateboard">
<part partid="11" name="board"/>
<part partid="12" name="wheel"/>
</part>
<part partid="20" name="canoe"/>
</parttree>
強く型指定されたデータと弱く型指定されたデータは、両方とも重要な XMLデータです。 このドキュメントのほとんどのクエリはDTDで規定された弱く型指定されたデータを中心としており、XML Schemaの単純データ型や名前付けされた複合型は含んでいません。 この記述例は、XQuery がXML Schema[XMLSchema0]による強く型指定されたデータを使用した型をサポートしていることを解説します。
注意:
このドキュメントの将来のバージョンでは、型指定のシステムに関する更にいくつかの記述例を提供するつもりです。 その場合には、静的型チェックといった他の型指定システムの側面を説明するでしょう。
この例のスキーマは、XML Schema Primer から抜き出した国際注文書スキーマです。国際注文書スキーマは住所のスキーマを取り込んでいます。 主たるスキーマを、つぎに示します。
<schema targetNamespace="http://www.example.com/IPO"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:ipo="http://www.example.com/IPO">
<annotation>
<documentation
xml:lang="en">
International
Purchase order schema for Example.com
Copyright
2000 Example.com. All rights reserved.
</documentation>
</annotation>
<!-- include
address constructs -->
<include
schemaLocation="http://www.example.com/schemas/address.xsd"/>
<element
name="purchaseOrder" type="ipo:PurchaseOrderType"/>
<element
name="comment" type="string"/>
<complexType
name="PurchaseOrderType">
<sequence>
<element
name="shipTo" type="ipo:Address"/>
<element
name="billTo" type="ipo:Address"/>
<element
ref="ipo:comment" minOccurs="0"/>
<element
name="items" type="ipo:Items"/>
</sequence>
<attribute
name="orderDate" type="date"/>
</complexType>
<complexType
name="Items">
<sequence>
<element
name="item" minOccurs="0" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="productName" type="string"/>
<element name="quantity">
<simpleType>
<restriction base="positiveInteger">
<maxExclusive value="100"/>
</restriction>
</simpleType>
</element>
<element name="USPrice" type="decimal"/>
<element ref="ipo:comment" minOccurs="0"/>
<element name="shipDate" type="date"
minOccurs="0"/>
</sequence>
<attribute name="partNum" type="ipo:SKU" use="required"/>
</complexType>
</element>
</sequence>
</complexType>
<simpleType
name="SKU">
<restriction
base="string">
<pattern
value="\d{3}-[A-Z]{2}"/>
</restriction>
</simpleType>
</schema>
住所を構成するスキーマは、次のとおりです。
<schema targetNamespace="http://www.example.com/IPO"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:ipo="http://www.example.com/IPO"
elementFormDefault="qualified">
<annotation>
<documentation
xml:lang="en">
Addresses for International Purchase order schema
Copyright 2000 Example.com. All rights reserved.
</documentation>
</annotation>
<complexType
name="Address">
<sequence>
<element name="name" type="string"/>
<element name="street" type="string"/>
<element name="city" type="string"/>
</sequence>
</complexType>
<complexType
name="USAddress">
<complexContent>
<extension base="ipo:Address">
<sequence>
<element name="state" type="ipo:USState"/>
<element name="zip" type="positiveInteger"/>
</sequence>
</extension>
</complexContent>
</complexType>
<complexType
name="UKAddress">
<complexContent>
<extension base="ipo:Address">
<sequence>
<element name="postcode" type="ipo:UKPostcode"/>
</sequence>
<attribute name="exportCode" type="positiveInteger"
fixed="1"/>
</extension>
</complexContent>
</complexType>
<!-- other
Address derivations for more countries -->
<simpleType
name="USState">
<restriction
base="string">
<enumeration value="AK"/>
<enumeration value="AL"/>
<enumeration value="AR"/>
<!-- and so on ... -->
<enumeration value="PA"/>
</restriction>
</simpleType>
<!-- simple
type definition for UKPostcode -->
<simpleType
name="UKPostcode">
<restriction base="string">
<pattern value="[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][A-Z]{2}"/>
</restriction>
</simpleType>
</schema>
クエリで使用するサンプルデータは、次のとおりです。
<?xml version="1.0"?>
<ipo:purchaseOrder
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ipo="http://www.example.com/IPO"
orderDate="1999-12-01">
<shipTo exportCode="1" xsi:type="ipo:UKAddress">
<name>Helen Zoe</name>
<street>47 Eden Street</street>
<city>Cambridge</city>
<postcode>CB1 1JR</postcode>
</shipTo>
<billTo xsi:type="ipo:USAddress">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Old Town</city>
<state>PA</state>
<zip>95819</zip>
</billTo>
<items>
<item partNum="833-AA">
<productName>Lapis necklace</productName>
<quantity>1</quantity>
<USPrice>99.95</USPrice>
<ipo:comment>Want this for the holidays!</ipo:comment>
<shipDate>1999-12-05</shipDate>
</item>
</items>
</ipo:purchaseOrder>
英国への請求書の枚数を計算します。
XQuery記述例:
declare namespace
ipo="http://www.example.com/IPO"
count(
document("ipo.xml")//ipo:shipTo[.
instance of element of type ipo:UKAddress]
)
このデータセットには、住所用のデータには国の名前が含まれていません。また、あて先(shipTo)要素の名前は、品物が送られる国にかかわらず同じです。 スキーマでは、型だけが英国の住所を識別することを可能にします。 英国の住所のための1つの住所型と米国の住所型があり、両方とも共通の基底クラスから派生しています。 上記のクエリでは、英国へ送られた請求書を識別するために UKAddress 型を使用します。
郵便番号が正しいかどうかチェックするために、米国の住所をテストする関数を記述します。
"zips.xml" と呼ばれるファイルに郵便番号データが格納されると仮定します。ファイルは、以下のとおりです。
<zips>
<row>
<city>Old Town</city>
<state>PA</state>
<zip>95819</zip>
</row>
<row>
<city>Durham</city>
<state>NC</state>
<zip>27701</zip>
</row>
<row>
<city>Durham</city>
<state>NC</state>
<zip>27703</zip>
</row>
</zips>
XQuery記述例:
import schema "ipo.xsd"
import schema "zips.xsd"
declare namespace
ipo="http://www.example.com/IPO"
declare namespace
zips="http://www.example.com/zips"
define function
zip-ok($a as element of type ipo:USAddress)
as xs:boolean
{
some $i in
document("zips.xml")/zips:zips/zips:row
satisfies
$i/zips:city = $a/ipo:city
and $i/zips:state = $a/ipo:state
and $i/zips:zip = $a/ipo:zip
}
間違ったアドレス(zip)要素をパラメータにこの関数を呼び出すと、エラーが発生します。 例えば、zip-ok()関数をUKAddress 型の要素をパラメータに呼び出すことはできません。
適切な住所型を持っているすべての要素で使用できるように、この関数のパラメータは要素名ではなく型が指定されていることに注意してください。 例えば、サンプルスキーマでは、'billTo' および 'shipTo' は両方とも USAddress 型を持つかもしれない2つの異なる要素です。
郵便番号が正しいかどうかチェックするために、英国の住所をテストする関数を記述します。
"postals.xml" と呼ばれるファイルに郵便番号データのテストに必要な情報が格納されているとします。ファイルは、以下のとおりです。
<postals>
<row>
<city>Cambridge</city>
<prefix>CB</prefix>
</row>
<row>
<city>Oxford</city>
<prefix>OX</prefix>
</row>
</postals>
XQuery記述例:
import schema "ipo.xsd"
import schema "postals.xsd"
declare namespace
ipo="http://www.example.com/IPO"
declare namespace
pst="http://www.example.com/postals"
define function
postal-ok($a as element of type ipo:UKAddress)
as xs:boolean
{
some $i in
document("postals.xml")/pst:postals/pst:row
satisfies
$i/pst:city = $a/ipo:city
and xf:starts-with($a/ipo:postcode, $i/pst:prefix)
}
誤った郵便番号(英国の住所か米国の住所かに依存しますが)を含む注文書を返します。
XQuery記述例:
import schema "ipo.xsd"
import schema "postals.xsd"
import schema "zips.xsd"
declare namespace
ipo="http://www.example.com/IPO"
declare namespace
pst="http://www.example.com/postals"
declare namespace
zips="http://www.example.com/zips"
define function
postal-ok($a as element of type ipo:UKAddress)
as xs:boolean
{
some $i in
document("postals.xml")/pst:postals/pst:row
satisfies
$i/pst:city = $a/ipo:city
and starts-with($a/ipo:postcode, $i/pst:prefix)
}
define function
zip-ok($a as element of type ipo:USAddress)
as xs:boolean
{
some $i in
document("zips.xml")/zips:zips/zips:row
satisfies
$i/zips:city = $a/ipo:city
and $i/zips:state = $a/ipo:state
and $i/zips:zip = $a/ipo:zip
}
define function
address-ok($a as element of type ipo:Address)
as xs:boolean
{
typeswitch
($a)
case element of type ipo:USAddress $zip
return zip-ok($zip)
case element of type ipo:UKAddress $postal
return postal-ok($postal)
default return false()
}
for $p in document("ipo.xml")//ipo:purchaseOrder
where not( address-ok($p/ipo:shipTo)
and address-ok($p/ipo:billTo))
return $p
このクエリは、Q2 および Q3 で定義された関数を呼び出します。
関数address-ok()が、ipo:Address 型であるすべて属性を許可することに注意してください。ipo:Address型は、ipo:UKAddress型および ipo:USAddress型のベースです。 また、米国あるいは英国の両方の住所を対応できるように、この関数がtypeswitchを使用していることに注意してください。 これはポリモルフィズムの基本的な形態です。
送付先住所の名前が、請求先住所の名前と一致しない注文書を返すクエリを記述します。
XQuery記述例:
import schema "ipo.xsd"
declare namespace
ipo="http://www.example.com/IPO"
define function
names-match( $s as element ipo:shipTo context ipo:purchaseOrder,
$b as element ipo:billTo context ipo:purchaseOrder)
as xs:boolean
{
$s/ipo:name = $b/ipo:name
}
for $p in document("ipo.xml")//ipo:purchaseOrder
where not( names-match(
$p/ipo:shipTo, $p/ipo:billTo ) )
return $p
この関数では、パラメーターの指定に型名ではなく要素名を使用することに注意してください。関数が間違って2つのipo:billTo要素で呼ばれた場合には、クエリはエラーを返すべきです。 しかし、送付先住所の型と請求先住所の型が違うのは、間違いではありません。
さらに、これらの要素が両方とも注文書内でのみ定義されているローカル要素であることに注意してください。 これらの要素はグローバルに定義されていないので、パラメーターには名前が定義されるスキーマを指定します(XMLでは、ローカルの名前が名前衝突を防ぎます。しかし、それはデータの隠蔽形式は行使しません)。
価格の少なくとも1つがUSPriceにもかかわらず、請求先住所がUSAddress でない注文書を見つけます。
XQuery記述例:
import schema "ipo.xsd"
declare namespace
ipo="http://www.example.com/IPO"
for $p in document("ipo.xml")//ipo:purchaseOrder,
$s in $p/ipo:shipTo
where not( $s instance
of element of type ipo:USAddress)
and exists(
$p//ipo:USPrice )
return $p
このスキーマでは、価格は共通のベース型からではなくdecimal から直接派生しています。 これは、米国価格を識別するために要素名 USPrice を使用しなければならないことを意味します。 住所は型階層の一部であり、要素名 ipo:shipTo は住所が米国価格かどうかは伝えません。そのため、私たちは型をテストします。
この例では、価格がすべて USPrice 要素であることをスキーマが明示するように設計してあります。 しかしながら、構造から得られる情報を型情報から得られる情報と容易に結合できる能力を説明します。
comment 要素のテキストを返す関数を記述します。 1999-12-01の日付にHelen Zoeに送付した品物で、各shipComment要素に対して、この関数を呼びます。
XML Schema Primerの例では、置換グループとして次の例を使用します:
<element name="comment"
type="string"/>
. . .
<element name="shipComment"
type="string"
substitutionGroup="ipo:comment"/>
<element name="customerComment"
type="string"
substitutionGroup="ipo:comment"/>
XML Schema Primerの例では、これらの置換グループを例証するために次のサンプルデータを提供します:
<items>
<item
partNum="833-AA">
<productName>Lapis necklace</productName>
<quantity>1</quantity>
<USPrice>99.95</USPrice>
<ipo:shipComment>
Use gold wrap if possible
</ipo:shipComment>
<ipo:customerComment>
Want this for the holidays!
</ipo:customerComment>
<shipDate>1999-12-05</shipDate>
</item>
</items>
XQuery記述例:
import schema "ipo.xsd"
declare namespace
ipo="http://www.example.com/IPO"
define function
comment-text($c as element ipo:comment)
as xs:string
{
string( $c )
}
for $p in document("ipo.xml")//ipo:purchaseOrder,
$t in comment-text( $p//ipo:shipComment )
where $p/ipo:shipTo/ipo:name="Helen
Zoe"
and $p/ipo:orderDate = date("1999-12-01")
return $t
このクエリでは、関数はipo:commentを属性名として指定します。 しかし、ipo:comment の置換グループの任意の要素もこの関数に渡されるかもしれません。 これは、ipo:shipComment 要素あるいは ipo:customerComment 要素のための同じ関数を呼び出すことができることを意味します。 例えば、次のクエリも成功します:
for $p in document("ipo.xml")//ipo:purchaseOrder
where $p/ipo:shipTo/ipo:name="Helen
Zoe"
and $p/@orderDate
= date("1999-12-01")
return comment-text(
$p//ipo:customerComment )
ipo:comment の置換グループを含み、1999-12-01 の日付に Helen Zoe に送付した品物のすべてのcomment 要素を返します。
XQuery記述例:
import schema "ipo.xsd"
declare namespace
ipo="http://www.example.com/IPO"
for $p in document("ipo.xml")//ipo:purchaseOrder
where $p/ipo:shipTo/ipo:name="Helen
Zoe"
and $p/@orderDate
= date("1999-12-01")
return ($p//ipo:customerComment
| $p//ipo:shipComment | $p//ipo:comment )
この記述例には、問題があります。 現在のWorking Draftでは、数え上げることなく、置換グループ中のすべての要素を検索することはできません。 これはワーキンググループで議論中です。
品物(item)要素かその他の要素かにかかわらず、要素上で見つかったコメントをすべて返す関数を記述します。
XQuery記述例:
import schema "ipo.xsd"
declare namespace
ipo="http://www.example.com/IPO"
define function
comments-for-element( $e as element )
as ipo:comment*
{
let $c :=
$e/(ipo:customerComment | ipo:shipComment | ipo:comment)
return $c
}
このスキーマでは、コメントは発注書あるいは品物に存在します。より完全なスキーマでは、その他のエリアにも存在するかもしれません。 この関数は、要素の名前に関わらず、要素上で見つかったコメントをすべて返します。パラメータにはどんな要素でも認められるように、関数を記述する必要があります。
US databaseを使用して、billTo要素にリストされた人が借金の踏み倒し屋(a deadbeat)であると知られているかどうかを割り出す関数を記述します。
このクエリは、"www.usa-deadbeats.com" が借金の踏み倒し屋のデータベースを所有していると仮定します。
XQuery記述例:
import schema "ipo.xsd"
declare namespace
ipo="http://www.example.com/IPO"
define function
deadbeat( $b as element ipo:billTo of type ipo:USAddress )
as xs:boolean
{
$b/ipo:name
= document("www.usa-deadbeats.com/current")/deadbeats/row/name
}
この関数が、要素名と型の両方を指定することに注意してください。これは、間違って送付先住所に対してこの関数を呼び出したりして、贈り物の受取人を当惑させないためです。また、型を指定するのは、他の国々の借金の踏み倒し屋を見つけるために、他のデータベースを使用する必要がある場合のためです。
一連の品物(item)要素の合計価格を計算する関数を記述します。
XQuery記述例:
import schema "ipo.xsd"
declare namespace
ipo="http://www.example.com/IPO"
define function
total-price( $i as element ipo:item* )
as xs:decimal
{
let $subtotals
:= for $s in $i return $s/ipo:quantity * $s/ipo:USPrice
return sum(
$subtotals )
}
以下に、(税と送料を計算する前に)請求書に記述する合計を得るために定義した関数を呼び出すクエリを示します:
import schema "ipo.xsd"
declare namespace
ipo="http://www.example.com/IPO"
for $p in document("ipo.xml")//ipo:purchaseOrder
where $p/ipo:shipTo/ipo:name="Helen
Zoe"
and
$p/ipo:orderDate = date("1999-12-01")
return total-price($p//ipo:item)
このクエリは、パラメータとしてシーケンスを渡す必要性を示しています。
上記のクエリは、同じ日に同一人物に複数の注文書が送付されることはないという仮定の下で動作します。 このスキーマには、注文書のための一意な識別子はありません。 もし存在していれば、注文書を選択するためにそれを使用していたでしょう。
[XMLSchema0]は、地域別にどのような製品がどのぐらい売れたかを示す四半期レポートです。結果は、次のようなレポートになります:
<purchaseReport
xmlns="http://www.example.com/Report"
period="P3M"
periodEnding="1999-12-31">
<regions>
<zip code="95819">
<part
number="872-AA" quantity="1"/>
<part
number="926-AA" quantity="1"/>
<part
number="833-AA" quantity="1"/>
<part
number="455-BX" quantity="1"/>
</zip>
<zip code="63143">
<part
number="455-BX" quantity="4"/>
</zip>
</regions>
<parts>
<part number="872-AA">Lawnmower</part>
<part number="926-AA">Baby
Monitor</part>
<part number="833-AA">Lapis
Necklace</part>
<part number="455-BX">Sturdy
Shelves</part>
</parts>
</purchaseReport>
以下に、上記のレポートのためのスキーマを示します:
<schema targetNamespace="http://www.example.com/Report"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:r="http://www.example.com/Report"
xmlns:xipo="http://www.example.com/IPO"
elementFormDefault="qualified">
<!-- for
SKU -->
<import namespace="http://www.example.com/IPO"/>
<annotation>
<documentation
xml:lang="en">
Report
schema for Example.com
Copyright
2000 Example.com. All rights reserved.
</documentation>
</annotation>
<element
name="purchaseReport">
<complexType>
<sequence>
<element name="regions" type="r:RegionsType">
<keyref name="dummy2" refer="r:pNumKey">
<selector xpath="r:zip/r:part"/>
<field xpath="@number"/>
</keyref>
</element>
<element name="parts" type="r:PartsType"/>
</sequence>
<attribute
name="period" type="duration"/>
<attribute
name="periodEnding" type="date"/>
</complexType>
<unique
name="dummy1">
<selector
xpath="r:regions/r:zip"/>
<field
xpath="@code"/>
</unique>
<key name="pNumKey">
<selector
xpath="r:parts/r:part"/>
<field
xpath="@number"/>
</key>
</element>
<complexType
name="RegionsType">
<sequence>
<element
name="zip" maxOccurs="unbounded">
<complexType>
<sequence>
<element name="part" maxOccurs="unbounded">
<complexType>
<complexContent>
<restriction base="anyType">
<attribute name="number" type="xipo:SKU"/>
<attribute name="quantity" type="positiveInteger"/>
</restriction>
</complexContent>
</complexType>
</element>
</sequence>
<attribute name="code" type="positiveInteger"/>
</complexType>
</element>
</sequence>
</complexType>
<complexType
name="PartsType">
<sequence>
<element
name="part" maxOccurs="unbounded">
<complexType>
<simpleContent>
<extension base="string">
<attribute name="number" type="xipo:SKU"/>
</extension>
</simpleContent>
</complexType>
</element>
</sequence>
</complexType>
</schema>
このレポートは米国内の郵便番号別製品リストであり、前のクエリで使用した国外の購買レポートとは別です。こうした米国内のリストは、XML Schema Primerに名前空間なしで定義されています。以下に、XML Schema Primerから抜粋した例を示します:
<?xml version="1.0"?>
<purchaseOrder
orderDate="1999-10-20">
<shipTo country="US">
<name>Alice Smith</name>
<street>123 Maple Street</street>
<city>Mill Valley</city>
<state>CA</state>
<zip>90952</zip>
</shipTo>
<billTo country="US">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Old Town</city>
<state>PA</state>
<zip>95819</zip>
</billTo>
<comment>Hurry, my lawn is going wild!</comment>
<items>
<item partNum="872-AA">
<productName>Lawnmower</productName>
<quantity>1</quantity>
<USPrice>148.95</USPrice>
<comment>Confirm this is electric</comment>
</item>
<item partNum="926-AA">
<productName>Baby Monitor</productName>
<quantity>1</quantity>
<USPrice>39.98</USPrice>
<shipDate>1999-05-21</shipDate>
</item>
</items>
</purchaseOrder>
以下が、米国内購買リストを含んだレポートを生成するためのクエリです:
declare namespace
rpt="http://www.example.com/Report"
let $orders := collection("orders")/purchaseOrder
[orderDate ge date("1999-09-01")
and orderDate le date("1999-12-31")]
let $items := $orders/items/item
let $zips := distinct-values($orders/billTo/zip)
let $parts := distinct-values($items/@partNum)
return
<rpt:purchaseReport>
<rpt:regions>
{
for $zip in $zips
order by $zip
return
<rpt:zip code="{data($zip)}">
{
for $part in $parts
let $hits := $orders[ billTo/zip = $zip and items/item/@partNum = $part]
let $quantity := sum($hits//item[@partNum=$part]/quantity)
where count($hits) > 0
order by $part
return
<rpt:part number="{data($part)}" quantity="{$quantity}"/>
}
</rpt:zip>
}
</rpt:regions>
<rpt:parts>
{
for $part in $parts
return
<rpt:part number="{data($part)}">
{
let $i := distinct-values($items[@partNum = $part])
return string-value($i/productName)
}
</rpt:part>
}
</rpt:parts>
</rpt:purchaseReport>
このドキュメントで使用している記述例を作成していただいたXML Query Working Groupのメンバーに感謝いたします。
各記述例の作成者は、次の方々です:
記述例 "R" |
Don Chamberlin |
|
記述例 "XMP" |
Mary Fernandez, Jerome Simeon, Phil Wadler |
|
記述例 "TREE" |
Jonathan Robie |
|
記述例 "PARTS" |
Michael Rys |
|
記述例 "NS" |
Ingo Macherius |
|
記述例 "STRING " |
Umit Yalcinalp |
|
記述例 "SEQ" |
Jonathan Robie |
|
記述例 "SGML" |
Paula Angerstein |
|
記述例 "STRONG" |
Jonathan Robie & Phil Wadler |
スキーマおよびデータは[XMLSchema0]から抜粋 |
記述例 "XMP"は、以前に[Fernandez]で公表されたことがあります。記述例"Tree"と記述例"Seq"は、以前に[Robie99]で公表されたことがあります。
また、ドラフトの初期バージョンに対してコメントしていただいたW3C Working Groupsに感謝いたします。さらに、貴重な助言をいただきましたMichael Dyckに感謝したいと思います。
以下に、この記述例で参照したWGの資料をあげます。
Cotton98