SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

XQueryの制御構造の活用

XQueryの使い方の勘所

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

 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

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

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
letコマンドの利用

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

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

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Kurt Cagle(Kurt Cagle)

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

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3011 2008/09/18 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング