CodeZine(コードジン)

特集ページ一覧

XQueryの制御構造の活用

XQueryの使い方の勘所

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2008/09/18 14:00

 XQuery言語はXML形式のSQLであり、XPath 2.0を単一のスカラー値だけでなく、値の集合も操作できるように拡張したものです。本稿では、XQueryの特徴と、その制御構造の使い方について解説します。

目次

XQueryの特徴

 以前、データベースプログラマである同僚の一人が、初期のXQueryの実装をしばらく使ってみて、この言語をニコニコ言語と評しました。それは言語のわかりやすさと関係するのかと訊いたところ、彼はハンガリー訛りの英語でこう答えました。「まさか、言語自体は難物だよ。だけど、ニコニコマーク (: :) がコメントの区切り記号になっているから、たとえデータベースがずたずたでもニコニコしてしまうわけさ」。

 彼の意見はこの言語をあからさまに非難するものではありませんが、XQueryについてのある事実、つまりXQueryの構造は一般の言語に似ているが、その違いの部分で大きくつまずく場合があるということをよく示しています。XQueryは習得の困難な言語ではありませんが、どうしてうまく動かないか知ろうという気にさせる言語でもあります。

XQueryの制御構造

 XQueryの制御構造はFLOWRという風変わりな頭字語で呼ばれてきました。これは、その言語で使われる特に重要なXQuery構造(すべてではない)の略称で、FLOWR自体は次の5つの操作を表します。

  • For
  • Let
  • Order by
  • Where
  • Return

 このうちの4つについては、SQLに類似の構造があります。

  • SELECT
  • SET
  • ORDER BY
  • WHERE

 これらの用語は集合に項目を割り当てる、または集合から項目を取り出すために使われます。

XQueryの使いどころ

 XQueryは''集合操作''言語です。単一のスカラー値よりも情報の集合を操作することに主眼が置かれます。また、集合操作言語という点で、その仕様に組み込まれているXPath 2.0言語を置き換えるよりも、それを拡張することを目指しています。実際、突き詰めていくと、XQueryの大部分はXPathの制御言語をラップする仕組みの1つに過ぎず、そのやり方はXSLTがXPathにテンプレート言語を結び付けるのとどこか似ています。

 こうした理由により、XQueryを操作するとき、この言語を最も効果的に使うには、最初にXPath 2内で可能な限り多くのことを行い、XPath 2ではもう立ち行かなくなったところでXQueryのコマンド構造を利用するという方法をとるべきです。

 たとえば、従業員レコードのコレクションで構成されるXMLデータソースがあると仮定します。現在、それらはファイル「employees.xml」に入っています(リスト1を参照)。

リスト1 Employees.xml
<?xml version="1.0" encoding="UTF-8"?>
<employees>
    <employee id="be129">
        <firstname>Jane</firstname>
        <lastname>Doe</lastname>
        <title>Engineer</title>
        <division>Materials</division>
        <building>327</building>
        <room>19</room>
        <supervisor>be131</supervisor>
    </employee>
    <employee id="be130">
        <firstname>William</firstname>
        <lastname>Defoe</lastname>
        <title>Accountant</title>
        <division>Accts Payable</division>
        <building>326</building>
        <room>14a</room>
    </employee>
    <employee id="be131">
        <firstname>Jack</firstname>
        <lastname>Dee</lastname>
        <title>Engineering Manager</title>
        <division>Materials</division>
        <building>327</building>
        <room>21</room>
    </employee>
    <employee id="be132">
        <firstname>Sandra</firstname>
        <lastname>Rogers</lastname>
        <title>Engineering</title>
        <division>Materials</division>
        <building>327</building>
        <room>22</room>
    </employee>
    <employee id="be133">
        <firstname>Steve</firstname>
        <lastname>Casey</lastname>
        <title>Engineering</title>
        <division>Materials</division>
        <building>327</building>
        <room>24</room>
    </employee>
    <employee id="be135">
        <firstname>Michelle</firstname>
        <lastname>Michaels</lastname>
        <title>COO</title>
        <division>Management</division>
        <building>216</building>
        <room>264</room>
    </employee>
</employees>

 このとき、各従業員に順にコンテキストを設定するにはfor文を使用します。次のコードは、リスト中の順番で各従業員を出力する単純なXQueryスクリプトです。

for $employee in doc("employees.xml")/employees/employee
return $employee[/s]

 この例では、従業員要素のシーケンスが、対応する各従業員の本体と共に返されます。もちろん、このシーケンスが正確にどうレンダリングされるかは、使用するXQueryの実装によって異なります。たとえば、Saxon 9のXQueryエンジンを使用した場合、出力はリスト2のようになります。

リスト2 XQueryスクリプトforSeq1.xqをSaxonで出力した例
result:sequence xmlns:result="http://saxon.sf.net/xquery-results"
                 xmlns:xs="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <result:element>
      <employee id="be129">
        <firstname>Jane</firstname>
        <lastname>Doe</lastname>
        <title>Engineer</title>
        <division>Materials</division>
        <building>327</building>
        <room>19</room>
        <supervisor>be131</supervisor>
      </employee>
   </result:element>
   <result:element>
      <employee id="be130">
        <firstname>William</firstname>
        <lastname>Defoe</lastname>
        <title>Accountant</title>
        <division>Accts Payable</division>
        <building>326</building>
        <room>14a</room>
      </employee>
   </result:element>
   </result:element>
    <!-- more results -->
</result:sequence>

 一方、eXist XQueryエンジンを使用した場合は、コンテナやクロージャを持たない要素ノードのシーケンスが返されます。その主な理由は、Saxonでは出力がXMLオブジェクトになるものと仮定されるのに対し(そのために何らかのコンテナが必要となる)、XQueryではそのような仮定がないことです。クエリ全体をXMLコンテナに入れれば、このラッパー問題を回避できます。

<employee_set>{
for $employee in doc("employees.xml")/employees/employee
return $employee}
</employee_set>

 Saxonの場合、この出力はよく似ていますが、完全に同じにはなりません(リスト3を参照)。

リスト3 ForSeq2.xqの結果
<result:sequence xmlns:result="http://saxon.sf.net/xquery-results"
                 xmlns:xs="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <result:element>
      <employee_set>
         <employee id="be129">
            <firstname>Jane</firstname>
            <lastname>Doe</lastname>
            <title>Engineer</title>
            <division>Materials</division>
            <building>327</building>
            <room>19</room>
            <supervisor>be131</supervisor>
         </employee>
         <employee id="be130">
            <firstname>William</firstname>
            <lastname>Defoe</lastname>
            <title>Accountant</title>
            <division>Accts Payable</division>
            <building>326</building>
            <room>14a</room>
         </employee>
          <!-- more employees -->
      </employee_set>
   </result:element>
</result:sequence>

 for $item in $seqという式は、やや誤解を招く可能性があります。基本的にfor文はシーケンス内を反復処理するので、$item変数にはシーケンス内の各項目への内部ポインタが順に渡され、その$itemのコピーが渡されることはありません。つまり、$itemコンテキスト変数は、基本となるXML(または関連する)データモデル内の構造を参照していることと、その結果がこのコンテキストに基づくシーケンスになるという点において、「ライブ(live)」であると言えます。

 たとえば次の式では、

for $employee in doc("employees.xml")/employees/employee 
    order by $employee/lastname ascending
    return $employee

 従業員のリストが従業員の姓の順に返されます。要するに、order by文はリストを指定の条件で並べ替えた仮想的なシーケンスを作ります。

for $employee in doc("employees.xml")/employees/employee order by $employee/lastname ascending return $employee

 上記のうち、太字部分の式が仮想的なシーケンスを表します。


  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

あなたにオススメ

著者プロフィール

  • japan.internet.com(ジャパンインターネットコム)

    japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.com や EarthWeb.c...

  • Kurt Cagle(Kurt Cagle)

    ライター、情報アーキテクト、XML News NetworkとMetaphorical Webのウェブマスター。カナダ、ブリティッシュコロンビア州のビクトリア在住。XMLToday.orgの編集長、O'Reilly Mediaの寄稿編集者。現在、XBRLに関する著書を執筆中。彼のTwitterはtw...

バックナンバー

連載:japan.internet.com翻訳記事

もっと読む

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5