このドキュメントは、W3CのXML Query Use Casesのワーキングドラフトの翻訳です。正式なのはW3Cのサイトにある英語版であり、この翻訳ではありません。この翻訳は原文と技術的に等価なことを意図していますが、翻訳上の誤りが存在する可能性があります。

原文は次のURLで参照することができます:
   http://www.w3.org/TR/2002/WD-xmlquery-use-cases-20021115/
翻訳者:
   山本 浩一(NTTソフトウェア株式会社)
   藤 孝幸(富士インフォックスネット株式会社)
   秋本 尚吾(日本オラクル株式会社)
   根来 元(日本ユニシス株式会社)

W3C

XML Query Use Cases

W3C ワーキングドラフト 2002年11月15日

本バージョン:
   http://www.w3.org/TR/2002/WD-xmlquery-use-cases-20021115/
最新バージョン:
   http://www.w3.org/TR/xmlquery-use-cases/
前バージョン:
   http://www.w3.org/TR/2002/WD-xmlquery-use-cases-20020816/
編集者:
   Don Chamberlin, IBMアルマデン研究センター <chamberlin@almaden.ibm.com >
   Peter Fankhauser, Infonyte有限会社 <fankhauser@infonyte.com>
   Daniela Florescu, XQRL <dana@xqrl.com>
   Massimo Marchiori, W3C/MIT/UNIVE <massimo@w3.org>
   Jonathan Robie, DataDirect Technologies <jonathan.robie@datadirect-technologies.com>

要約(アブストラクト)

このドキュメントは、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)


1 XML Query の記述例

このドキュメントで紹介する記述例は、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言語に含まれる保証はありません。

1.1 記述例("XMP"):代表例

本記述例は、データベースとドキュメントの両分野からの要求品物を例証するクエリ例からなっています。

1.1.1 ドキュメント型定義(DTD)

本記述例のほとんどのクエリ例は、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 )>

1.1.2 サンプルデータ

ここにあげたデータは、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>

1.1.3 Q5のためのDTD

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)>

1.1.4 Q5のためのサンプルデータ

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>

1.1.5 Q9のためのDTD

Q9は、次のDTDにもとづく”books.xml”という入力ドキュメントを使用します:

<!ELEMENT chapter (title, section*)>
<!ELEMENT section (title, section*)>
<!ELEMENT title (#PCDATA)>

1.1.6 Q9のためのデータ

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>

1.1.7 Q10のためのDTD

Q10は、次のDTDにもとづく”prices.xml”という名前の入力ドキュメントを使用します:

<!ELEMENT prices (book*)>
<!ELEMENT book (title, source, price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT source (#PCDATA)>
<!ELEMENT price (#PCDATA)>

1.1.8 Q10のためのデータ

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>

1.1.9 クエリと結果

1.1.9.1 Q1

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>

1.1.9.2 Q2

表題(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>

1.1.9.3 Q3

図書目録中の本の表題(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>

1.1.9.4 Q4

図書目録中の著者ごとに、著者名(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>

1.1.9.5 Q5

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.1.9.6 Q6

著者が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>

1.1.9.7 Q7

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>    

1.1.9.8 Q8

要素名が文字列"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>

1.1.9.9 Q9

“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>

1.1.9.10 Q10

“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>

1.1.9.11 Q11

著者(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>

1.1.9.12 Q12

表題が異なる本のうち、著者が同一の本(異なる順番で並んでいる場合も含めて)を見つけます。

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つのシークエンスは等しいとみなされます。シークエンスがノードのシークエンスである場合には、比較にはノードの値を使用します。

1.2 記述例("TREE"):階層構造を保持するクエリ

ドキュメント型のXMLには、テキストと要素が混ざり合い、しかも要素の多くはオプションであるという非常に柔軟な構造になっているものがあります。また、ドキュメント型XML は、ドキュメントごとに構造が大きく異なります。 これらのドキュメント型XML では、大抵の場合、要素の並べ方や入れ子にする仕方が非常に重要です。

1.2.1 詳細

XML Query言語には、オリジナルの階層を保持しながら、 ドキュメントから要素を抽出する能力が必要です。 この記述例では、本(Book)という名前の柔軟なドキュメント型XML をとおして、 この必要性を例証します。

1.2.2 ドキュメント型定義(DTD)

この記述例は、”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 >
]>

1.2.3 サンプルデータ

この記述例のクエリは、次のサンプルデータにもとづいています。

<?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>

1.2.4 クエリと結果

1.2.4.1 Q1

すべての節の名前をリストして、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>

1.2.4.2 Q2

すべての図(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>

1.2.4.3 Q3

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>

1.2.4.4 Q4

Book1中には、最上位の節(section)がいくつあるか数えます。

XQuery記述例:

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

期待される結果:

<top_section_count>2</top_section_count>

1.2.4.5 Q5

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>

1.2.4.6 Q6

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>

1.3 記述例("SEQ"):シークエンスにもとづくクエリ

この利用例は、ドキュメントに現われる要素であるシークエンスにもとづいたクエリを例証します。

1.3.1 詳細

シークエンスは従来のデータベースシステムやオブジェクトシステムのほとんどでは重要ではありませんが、 構造化されたドキュメントにおいては非常に重要になりえます。 この利用例では、医療報告書にもとづく一連のクエリを示します。

1.3.2 ドキュメント型定義(DTD)

この記述例は、“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)>
]>

1.3.3 サンプルデータ

この記述例のクエリは、次のサンプルデータによっています。

<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>

1.3.4 クエリと結果

1.3.4.1 Q1

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>

1.3.4.2 Q2

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>

1.3.4.3 Q3

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>

1.3.4.4 Q4

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)はありません。)

1.3.4.5 Q5

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>

1.4 記述例("R"):リレーショナルデータに対するアクセス

XML Query言語の重要な使用方法の1つとして、リレーショナルデータベースに 格納されたデータに対するアクセスがあります。ここでは、リレーショナルデータベースに格納されたデータにアクセスする 一例を示します。

1.4.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 )

1.4.2 ドキュメント型定義(DTD)

この記述例は、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)>
]>

1.4.3 サンプルデータ

インスタンスの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

1.4.4 クエリと結果

以下は、1999年2月1日にクエリを行ったと仮定した場合の結果です。

1.4.4.1 Q1

現在行われているオークションのすべての自転車の品物番号(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の定義とは一致していません。

1.4.4.2 Q2

すべての自転車について、品物番号(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>

1.4.4.3 Q3

信用度の格付け(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>

1.4.4.4 Q4

入札価格(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>

1.4.4.5 Q5

入札価格(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>

1.4.4.6 Q6

最高入札価格(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>

1.4.4.7 Q7

これまで自転車(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>

1.4.4.8 Q8

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>

1.4.4.9 Q9

データが利用できる範囲で、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>

1.4.4.10 Q10

入札価格(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>

1.4.4.11 Q11

これまで記録されたうちの最高入札価格(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>

1.4.4.12 Q12

これまで入札数が一番多かった品物(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.4.4.13 Q13

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>

1.4.4.14 Q14

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>

1.4.4.15 Q15

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>

1.4.4.16 Q16

登録されている全ユーザ(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>

1.4.4.17 Q17

全ての品物(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>

期待される結果:

<frequent_bidder />

(Q17の条件を満たすユーザはいません。)

1.4.4.18 Q18

全てのユーザ(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>

1.5 記述例("SGML"):Standard Generalized Markup Language

1.5.1詳細

このドキュメントとクエリの例は、もともと1992年のStandard Generalized Markup Language(SGML)の会議のために作成されたものです。理解しやすいように、ドキュメント型定義(DTD)とドキュメント例はSGML からXML に変換してあります。

1.5.2 ドキュメント型定義(DTD)

この例は、暗黙の(名前のない)入力データセットにもとづいています。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>

1.5.3 サンプルデータ

この記述例中のクエリは、次のサンプルデータにもとづいています。 クエリ結果を特定しやすいように、データには行番号をつけてあります。

 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>

1.5.4 クエリと結果

1.5.4.1 Q1

報告書(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にある要素。

1.5.4.2 Q2

序論(introduction)の中の全てのパラグラフの位置を特定します。("intro"要素内にある全ての"para"要素)

XQuery記述例:

<result>
  {
    input()//intro/para
  }
</result>

期待される結果:

開始タグが、行番号6, 11, 20, 27, 53, 56, 62, 90, 94にある要素

1.5.4.3 Q3

序論(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にある要素

1.5.4.4 Q4

第2章(chapter)の第3節(section)にある第2パラグラフ(paragraph)の位置を特定します。("report"中の2番目の"chapter"要素内の3番目の"section"要素の内の2番目の"para"要素。)

XQuery記述例:

<result>
  {
    (((input()//chapter)[2]//section)[3]//para)[2]
  }
</result>

期待される結果:

開始タグが、行番号67にある要素

1.5.4.5 Q5

機密扱いのパラグラフ(paragraph)の位置を特定します。 ("security"属性が値"c"であるすべての"para"要素)

XQuery記述例:

<result>
  {
    input()//para[@security = "c"]
  }
</result>

期待される結果:

開始タグが、行番号94にある要素

1.5.4.6 Q6

すべての節(section)の略称(shorttitle)をリストします。 (全ての"section"要素にある"shorttitle"属性の値を、それぞれ新しい要素の値として表現。)

XQuery記述例:

<result>
  {
    for $s in input()//section/@shorttitle
    return <stitle>{ $s }</stitle>
  }
</result>

期待される結果:

開始タグが、行番号23, 50, 59にある要素

1.5.4.7 Q7

全ての序論(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にある開始タグの直後の文字

1.5.4.8 Q8a

"is SGML"という文字列を含む表題(title)の節(section)をすべてリストします。("is SGML"という連続した文字列をその内容に持つ"title"要素を持っている全ての"section"要素)。 その文字列は、配下要素によって分断されていても構いません。

XQuery記述例:

<result>
  {
    input()//section[contains(string(.//title), "is SGML")]
  }
</result>

期待される結果:

開始タグが、行番号50, 59にある要素

1.5.4.9 Q8b

(Q8a)と同じですが、その文字列は配下要素によって分断されていないものだけをリストします。

XQuery記述例:

<result>
  {
    input()//section[contains(.//title/text(), "is SGML")]
  }
</result>

期待される結果:

開始タグが、行番号59 にある要素

1.5.4.10 Q9

報告書(report)の中のどこかにある相互参照(xref)によって関係づけられたトピック(topic)を全てリストします。("topicid"属性を持ち、その属性値が任意の"xref"要素の"xrefid"属性の値と同じである 全ての"topic"要素")

XQuery記述例:

<result>
  {
    for $id in input()//xref/@xrefid
    return input()//topic[@topicid = $id]
  }
</result>

期待される結果:

開始タグが、行番号65にある要素

1.5.4.11 Q10

"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に開始タグがある要素

1.6 記述例"STRING":ストリング検索

1.6.1 詳細

この記述例は、企業評価やPR、合併、買収などのデータを含む一連のニュースドキュメントをもとにしています。ある企業に関するニュースドキュメント内のテキストサーチのやり方をいくつかと、クエリの結果を企業評価やニュースの内容とマッチングさせる方法をいくつか示します。

この例では、ノードもしくは空の文字列が含まれていないかをテストするために、関数containsが使用されています。 もちろん、関数full-textを使用すればより強力なサーチが可能ですが、現段階では“Functions and Operators draft”に関数full-textは含まれていません。

1.6.2 ドキュメント型定義(DTD)

この記述例の暗黙の(名前のない)入力データセットの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 >

1.6.3 サンプルデータ

この記述例のクエリは、関数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>

1.6.4 クエリと結果

1.6.4.1 Q1

表題に"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>

1.6.4.2 Q2

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.6.4.3 Q4

企業とその提携企業の内の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を提訴

1.6.4.4 Q5

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.7 記述例"NS":名前空間を使用したクエリ

この記述例では、名前空間つきノード名に対する様々なクエリを行います。

1.7.1 詳細

この記述例がもとにしているシナリオは、 中立の立場に立つ調停者が、クライアントに代わって、 公開のオークションを行うというものです。 クライアントがこの仮想のサービスを利用する理由というのは、 名前を伏せるためであったり、 より安全な保険をかけるためであったり、 同時に1つ以上のマーケットに参加するためであったりします。 名前空間の以下の面が、この記述例によって示されます。

·         異なるソースからなるXMLデータが組み合わされた場合の、構文のあいまいさの解決

·         XLinksやXMLスキーマのようなあらかじめ定義されているモジュールの再利用

·         Dublin Coreのようなグローバル分類スキーマのサポート

サンプルデータは2レコードからなり、W3C XML Schemaのスキーマコンポジションであらかじめ定義されたスキーマと、モジュール分割された名前空間、そしてスキーマを作り出し参照を表現するためにXLinkを使います。 個々のレコードは、実行中のオークションを表しています。 このレコードには、競売人(つまり、会社の信用格付けシステム)と特定の物品(ジャズのレコード)が、 オークションでは知られたデータ(開始終了時間など)が フレームワークに組み込まれていて、名前空間を使ってこの3つの語彙を識別しています。

注意していただきたいのは、名前空間で限定された名前の突合せを行う前に、名前空間の接頭辞が名前空間のURIに 対して解決されていないといけないということです。 名前空間を提供するために、文字の接頭辞を使うのには 差し支えがあります。 更にいうと、名前空間の宣言する方法には、 いつくかの可能な方法があるということです。 つまり、名前空間の処理は、XML Information Setによって 処理された名前空間に対して行わればならいないということで、 XMLのテキスト表現に対してではないということです。

1.7.2 ドキュメント型定義(DTD)

DTDには名前空間との完全な互換性がなく 同じ名前空間内のノードの同等性を表現できませんが、 異なった名前空間プロキシを使えば可能です。 このドキュメントの後のバージョンは、ここにXML Schemaがここに追加されるべきです。

この記述例は、暗黙の(名前なしの)入力データセットを前提としてます。

1.7.3 サンプルデータ

<?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 &amp;
                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>

1.7.4 クエリと結果

1.7.4.1 Q1

サンプルデータで使われている名前空間(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>

1.7.4.2 Q2

競売に出されているレコード盤から、表題(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>

1.7.4.3 Q3

"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>

1.7.4.4 Q4

ドキュメント内の全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>

1.7.4.5 Q5

論評(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>

1.7.4.6 Q6

現在見ている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> 

1.7.4.7 Q7

売り手(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>

1.7.4.8 Q8

消極的な発言(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>

1.8 記述例"PARTS":再帰的部分展開

この記述例では、再帰クエリがどのように使われるかを明らかにします。データベースに蓄積されたフラットな構造から、任意の深さを持つ階層構造のドキュメントを構築します。

1.8.1 詳細

この記述例は、"部分展開"データベースを元にしています。 このデータベースが保持している情報は、部分が他の部分でどのように 使われるかというものです。

この記述例の入力は、"フラットな"ドキュメントで、それぞれのドキュメントの部分は、partIDと名前属性からなる部分(part)要素によって示されています。 個々の部分は、より大きな部分の一部であったり、 そうでなかったりします。 より大きな部分に含まれている場合は、そのより大きな部分のpartIDが部分構成(part of)要素に含まれます。 この入力ドキュメントはリレーショナルデータベースから 導き出されていて、それぞれの部分はテーブルのrowとして 格納されています。partIDがプライマリキーとなっていて、部分構成(part of)が、partIDを参照する外部キーとなっています。

この記述例のクエリは、外部キーに基づいた"フラットな"部分の展開の表現を階層表現に変換するもので、格納されている部分をドキュメントの構造に従ったものに変換します。

1.8.2 ドキュメント型定義(DTD)

入力データセットのDTDは、つぎのとおりです:

<!DOCTYPE partlist [
    <!ELEMENT partlist (part*)>
    <!ELEMENT part EMPTY>
    <!ATTLIST part
          partid  CDATA  #REQUIRED
          partof  CDATA  #IMPLIED
          name    CDATA  #REQUIRED>
]>

partIDpartOF属性が 順にtypeID、IDREFであったとしても、 リレーショナルデータベースから そのまま取り出してきたものでしょうから、 このスキーマでは文字型データとして扱います。 個々のpartOF属性は、 ちょうど1つのpartIDに一致します。 partOF属性を持たない部分は、 他の部分に含まれません。

出力データのDTD は、つぎのとおりです:

<!DOCTYPE parttree [
    <!ELEMENT parttree (part*)>
    <!ELEMENT part (part*)>
    <!ATTLIST part
          partid  CDATA  #REQUIRED
          name    CDATA  #REQUIRED>
]>

1.8.3 サンプルデータ

<?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>

1.8.4 クエリと結果

1.8.4.1 Q1

サンプルのドキュメントを、"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>

1.9 記述例("STRONG"):強く型指定されたデータを利用するクエリ

1.9.1 詳細

強く型指定されたデータと弱く型指定されたデータは、両方とも重要な XMLデータです。 このドキュメントのほとんどのクエリはDTDで規定された弱く型指定されたデータを中心としており、XML Schemaの単純データ型や名前付けされた複合型は含んでいません。 この記述例は、XQuery がXML Schema[XMLSchema0]による強く型指定されたデータを使用した型をサポートしていることを解説します。

注意:

このドキュメントの将来のバージョンでは、型指定のシステムに関する更にいくつかの記述例を提供するつもりです。 その場合には、静的型チェックといった他の型指定システムの側面を説明するでしょう。

1.9.2 スキーマ

この例のスキーマは、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>   

1.9.3 サンプルデータ

クエリで使用するサンプルデータは、次のとおりです。

<?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>

1.9.4 クエリと結果

1.9.4.1 Q1

英国への請求書の枚数を計算します。

XQuery記述例:

import schema "ipo.xsd"

declare namespace ipo="http://www.example.com/IPO"
count(
  document("ipo.xml")//ipo:shipTo[. instance of element of type ipo:UKAddress]
)

このデータセットには、住所用のデータには国の名前が含まれていません。また、あて先(shipTo)要素の名前は、品物が送られる国にかかわらず同じです。 スキーマでは、型だけが英国の住所を識別することを可能にします。 英国の住所のための1つの住所型と米国の住所型があり、両方とも共通の基底クラスから派生しています。 上記のクエリでは、英国へ送られた請求書を識別するために UKAddress 型を使用します。

1.9.4.2 Q2

郵便番号が正しいかどうかチェックするために、米国の住所をテストする関数を記述します。

"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つの異なる要素です。

1.9.4.3 Q3

郵便番号が正しいかどうかチェックするために、英国の住所をテストする関数を記述します。

"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)
}

1.9.4.4 Q4

誤った郵便番号(英国の住所か米国の住所かに依存しますが)を含む注文書を返します。

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を使用していることに注意してください。 これはポリモルフィズムの基本的な形態です。

1.9.4.5 Q5

送付先住所の名前が、請求先住所の名前と一致しない注文書を返すクエリを記述します。

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.9.4.6 Q6

価格の少なくとも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 要素であることをスキーマが明示するように設計してあります。 しかしながら、構造から得られる情報を型情報から得られる情報と容易に結合できる能力を説明します。

1.9.4.7 Q7

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 )   

1.9.4.8 Q8

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では、数え上げることなく、置換グループ中のすべての要素を検索することはできません。 これはワーキンググループで議論中です。

1.9.4.9 Q9

品物(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
}   

このスキーマでは、コメントは発注書あるいは品物に存在します。より完全なスキーマでは、その他のエリアにも存在するかもしれません。 この関数は、要素の名前に関わらず、要素上で見つかったコメントをすべて返します。パラメータにはどんな要素でも認められるように、関数を記述する必要があります。

1.9.4.10 Q10

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
}

この関数が、要素名と型の両方を指定することに注意してください。これは、間違って送付先住所に対してこの関数を呼び出したりして、贈り物の受取人を当惑させないためです。また、型を指定するのは、他の国々の借金の踏み倒し屋を見つけるために、他のデータベースを使用する必要がある場合のためです。

1.9.4.11 Q11

一連の品物(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)

このクエリは、パラメータとしてシーケンスを渡す必要性を示しています。

上記のクエリは、同じ日に同一人物に複数の注文書が送付されることはないという仮定の下で動作します。 このスキーマには、注文書のための一意な識別子はありません。 もし存在していれば、注文書を選択するためにそれを使用していたでしょう。

1.9.4.12 Q12

[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>

A 謝辞

このドキュメントで使用している記述例を作成していただいた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に感謝したいと思います。

B Change Log (Non-Normative)

B.1 2002年11月

  1. 全てのクエリを、最新のグラマーに変更しました。最大の変更は、sortby()句で指定していた並べ
    替えの指定をorder by句で指定するようにしたことです。
  2. 記述例"TEXT"を、記述例"STRING"という名前に変更しました。これは、全文検索検索ではなく、
    ストリング検索であることを明確にするためです。

  3. Phil Wadlerのレポート生成の例を、記述例"STRONG"に追加しました。

  4. 前バージョンに対するコメントからいくつかを反映し、小さなバグを修正しました。

C 参照資料(Non-Normative)

以下に、この記述例で参照したWGの資料をあげます。

Cotton98
   Candidate Requirements for XML Query, Paul Cotton and Ashok Malhotra, 1998.
   In Query Languages 98 (QL'98). (See http://www.w3.org/TandS/QL/QL98/pp/queryreq.html.)
DOM
   Document Object Model (DOM), Level 2 Specification. W3C Candidate Recommendation. (See
   http://www.w3.org/TR/1999/CR-DOM-Level-2-19991210.)
FandO
   XQuery 1.0 and XPath 2.0 Functions and Operators. W3C Working Draft. (See
   http://www.w3.org/TR/xquery-operators/.)
Fernandez
   XML Query Languages: Experiences and Exemplars, Mary Fernandez, Jerome Simeon, Philip
   Wadler, 1999. (See http://www.w3.org/1999/09/ql/docs/xquery.html.)
Infoset
   XML Information Set, W3C Recommendation 24 October 2001 , John Cowan, Richard Tobin
   (eds.), 2001. (See http://www.w3.org/TR/xml-infoset/.)
Maier98
   Database Desiderata for an XML Query Language, David Maier, 1998.
   In Query Languages 98 (QL'98). http://www.w3.org/TandS/QL/QL98/pp/maier.html.
   (See http://www.w3.org/TandS/QL/QL98/pp/maier.html.)
Namespaces
   Namespaces in XML. W3C Recommendation. (See
   http://www.w3.org/TR/1999/REC-xml-names-19990114/.)
Robie99
   The Tree Structure of XML Queries, Jonathan Robie. ( W3C members only)
   (See http://www.w3.org/XML/Group/1999/10/xquery-tree.html.)
XML
   Extensible Markup Language (XML), Version 1.0, Second Edition. W3C Recommendation.
   (See http://www.w3.org/TR/1998/REC-xml-19980210.)
XMLSchema0
   XML Schema Part 0: Primer, David C. Fallside (ed.), 2000.
   (See http://www.w3.org/TR/xmlschema-0/.)
XMLSchema1
   XML Schema Part 1: Structures, Henry S. Thompson, David Beech, Murray Maloney,
   Noah Mendelson (eds.), 2000. (See http://www.w3.org/TR/xmlschema-1/.)
XMLSchema2
   XML Schema Part 2: Datatypes, Paul V. Biron, Ashok Malhotra (eds.), 2000.
   (See http://www.w3.org/TR/xmlschema-2/.)
XPath
   XML Path Language (XPath) 2.0. W3C Working Draft.
   (See http://www.w3.org/TR/xpath20.)
XQuery
   XQuery 1.0: An XML Query Language. W3C Working Draft.
   (See http://www.w3.org/TR/xquery/.)
XSLT
   XSL Transformations (XSLT), Version 1.0. W3C Recommendation.
   (See http://www.w3.org/TR/1999/REC-xslt-19991116.)
Use Case Sample Queries
   Queries from this document, presented in a single file (See
   http://www.w3.org/TR/2002/WD-xmlquery-use-cases-20020816/xmlquery-use-case-queries.txt.)
XQuery Sample Queries
   Queries from the XQuery document, presented in a single file. (See
   http://www.w3.org/TR/2002/WD-xmlquery-use-cases-20020816/xquery-wd-queries.txt.)