ホーム  > X-plus >  XML活用事例

この記事を印刷する この記事を送る はてなブックマークに追加する
テキストリンクコードを取得する

CocoonによるWebサイト構築テクニック

2005年08月01日作成 

Cocoonを使ったWebサイト構築について2年弱にわたって連載を行ってきた。特に大量のコンテンツを保持しながら、同時に管理しやすいサイトを構築するのにCocoonが役立つことをご理解いただけたことと思う。最終回となる今回はXMLデータベースとの連携について取り上げよう。

本連載を通じて、CocoonはXMLデータを活用したWebサイトを構築するための環境であり、XMLデータを整理してWeb上に公開したい場合に有用であることを説明してきた。さて、XMLデータの量が多くなるにつれて、データの検索を行って、見つけたデータを表示することも必要になってくるだろう。

前々回および前回は、リレーショナルデータベースとCocoonを連携させる方法について説明した。もともとXMLで記述されていたデータであっても、表形式に整理することができればリレーショナルデータベースに格納することによって検索の性能を上げることができる。それをCocoonと連携させれば、データの効率的な管理が可能になるわけだ。

このように、リレーショナルデータベースは非常に有用な道具だが、XMLで記述されるデータの中にはリレーショナルデータベースに格納するには不便なものもある。たとえば、長い文章を含むデータや、データ構造の中に不規則な繰り返しが現れる場合、表形式のデータへのマッピングが困難になることが少なくない。そのような場合にはXMLデータベースを活用することを検討できる。XMLデータベースを使用すると、格納した多量のXMLデータの中から必要なデータを取り出して使用できるようになる。

XMLデータベース「Xindice」

Cocoonには、Apache XMLプロジェクトで開発/保守がなされているXMLデータベース「Xindice」(http://xml.apache.org/xindice/)が添付されており、CocoonをセットアップしただけでXindiceと連携した動作ができるようになっている1。Cocoon 2.1.7にはXindice 1.1b4が添付されており、XPathを使った検索とXUpdateを使った更新をサポートしている。

Xindiceを含め、多くのXMLデータベースはファイルシステムのディレクトリとよく似た構造の「コレクション」という単位にXMLドキュメントを整理して格納する(図 1)。トップレベルのコレクションには「db」という名前が付けられており、「/db」と表記する。各コレクションにはドキュメントを入れるほか、下位のコレクションを作成することもできる。なお、トップレベルコレクション「/db」には直接ドキュメントを格納することはできない。

XMLデータベースに対する操作は、基本的にコレクションの単位で行われる。コレクションを指定してドキュメントを取り出したり、コレクションを指定してXPathを使ったクエリーを行うのである。XPathを使ったクエリーでは、指定したコレクション中のそれぞれのドキュメントに対して同じ検索が実行され、それぞれの検索結果を合わせたものが結果として返却される。

Xindice管理ツールの使い方

CocoonにはXindiceを管理するためのツールは添付されていない。それで、Xindiceを使い始める前に管理ツールを入手しておくとよいだろう。

以下において、オリジナルのXindiceに添付されたコマンドラインベースの管理ツール「xindice.bat」をWindows環境で使う方法を説明する2。

1.Xindiceのホームページhttp://xml.apache.org/xindiceから「Download」をクリックし、「Binary (jar)」と示されたファイルをダウンロードして展開する。

2.表1に示す環境変数を設定する。たとえば、C:¥Java¥jakarta-tomcat-5.5.9にセットアップしたTomcatにCocoonを配備し、ダウンロードしたxml-xindice-1.1b4-jar.zipをC:¥Javaに展開した場合、リスト1のように設定することになる。

これで、XINDICE_HOME¥binに置かれた管理ツールxindice.batを使って、Cocoonと統合されたXindiceの管理が可能になった。

管理ツールを使って行うおもな作業には以下のものがある。

■コレクションのリスト:指定したコレクションに含まれるコレクションのリストを表示する

xindice lc -c コレクションURL

■コレクションの作成:指定した親コレクションに新しいコレクションを作成する

xindice ac -c 親コレクションURL -n 新コレクション名

■コレクションの削除:指定した親コレクション内のコレクションを削除する

xindice dc -c 親コレクションURL -n 削除するコレクション名

■ドキュメントのリスト:指定したコレクションに含まれるドキュメントのリストを表示する

xindice ld -c コレクションURL

■ドキュメントの追加:指定したコレクションにファイル名で指定したドキュメントを格納する。データベース内では指定したドキュメントキーで識別される3。

xindice ad -c コレクションURL -f ファイル名 -n ドキュメントキー

■ドキュメントの削除:指定したコレクションからドキュメントキーで指定したドキュメントを削除する

xindice dd -c コレクションURL -n ドキュメントキー

■ドキュメントの取得:指定したコレクション内にあるドキュメントキーで指定したドキュメントを取り出してファイルに保存する

xindice rd -c コレクションURL -n ドキュメントキー -f 出力ファイル名

その他のコマンドや引数の詳細については、Xindiceのホームページから「Commandline Tool Guide」をクリックして表示される情報を参照していただきたい。

ここまでで説明したとおり、Xindice管理ツールのすべてのコマンドで、-cオプションを使って処理の対象となるコレクションのURLを指定する必要がある。このURLの指定には、以下のような「XML:DB URL」と呼ばれる記法を使用する。

xmldb:データベースID://ホスト名またはIPアドレス/コレクション名

データベースIDとは、XMLデータベースの種類ごとに決まっている文字列であり、Xindiceでは「xindice」と「xindice-embed」の2種類がサポートされている。

「xindice」はネットワーク経由でホスト名またはIPアドレスで指定したマシン上で動作するXindiceにアクセスする4。

一方、「xindice-embed」を使うと、同一マシン上のXindiceにアクセスする5。この場合、ホスト名またはIPアドレスには何も書かない。同一マシンで動作するXindiceのコレクション「/db」にアクセスするには、以下のXML:DB URLを使う。

xmldb:xindice-embed:///db

具体的には、リスト 2のように実行すればXindice管理ツールを使ってXindiceのコレクション「/db」に含まれるコレクションのリストを得ることができる。Cocoonと統合したXindiceでは、初期状態ではXindiceデータベース自身が使用するコレクション「system」と「meta」の2つが存在し、Cocoonに添付されたサンプルを動作させると「cocoon」というコレクションが生成される(Cocoonに添付されたサンプルについてはコラムを参照)。

【リスト2:Xindiceのコレクション/dbに含まれるコレクションをリストする(強調表示したコマンドを入力)】
C:¥Java¥xindice-1.1b4¥bin>xindice lc -c xmldb:xindice-embed:///db
trying to register database
[INFO] DatabaseImpl - -Specified configuration file: 'C:¥Java¥jakarta-tomcat-5.5
.9¥webapps¥cocoon¥WEB-INF¥xindice.xml'
[INFO] Database - -Database points to C:¥Java¥jakarta-tomcat-5.5.9¥webapps¥cocoo
n¥WEB-INF¥db

        cocoon
        system
        meta

Total collections: 3

C:¥Java¥xindice-1.1b4¥bin>


管理ツールを使ってサンプルデータを登録する

それでは、実際に管理ツールを使ってサンプルデータをXindiceに格納してみよう6。以下の手順で2つのサンプルデータを登録する。

① 今回のサンプルデータを格納するためのコレクション「accessories」を作成する。
② 1つめのサンプルデータ「magupi.xml」をドキュメントキー「magupi」で登録する。
③ 2つめのサンプルデータ「ring.xml」をドキュメントキー「ring」で登録する。
④ コレクション「accessories」に含まれるドキュメントのリストを表示する。ドキュメント「magupi」と「ring」が登録されていることが確認できる。

この手順を実行するコマンドラインをリスト 3に、登録するサンプルデータをリスト 4とリスト 5に示す。

【リスト3:サンプルデータの登録】

C:¥Java¥xindice-1.1b4¥bin>xindice ac -c xmldb:xindice-embed:///db -n accessories

trying to register database
[INFO] DatabaseImpl - -Specified configuration file: 'C:¥Java¥jakarta-tomcat-5.5
.9¥webapps¥cocoon¥WEB-INF¥xindice.xml'
(中略)
[INFO] CollectionManager - -Created a new collection named 'accessories'
Created : xmldb:xindice-embed:///db/accessories

C:¥Java¥xindice-1.1b4¥bin>xindice ad -c xmldb:xindice-embed:///db/accessories -f
 c:¥temp¥magupi.xml -n magupi
trying to register database
(中略)
Added document xmldb:xindice-embed:///db/accessories/magupi

C:¥Java¥xindice-1.1b4¥bin>xindice ad -c xmldb:xindice-embed:///db/accessories -f
 c:¥temp¥ring.xml -n ring
trying to register database
(中略)
Added document xmldb:xindice-embed:///db/accessories/ring

C:¥Java¥xindice-1.1b4¥bin>xindice ld -c xmldb:xindice-embed:///db/accessories
trying to register database
[INFO] DatabaseImpl - -Specified configuration file: 'C:¥Java¥jakarta-tomcat-5.5
.9¥webapps¥cocoon¥WEB-INF¥xindice.xml'
[INFO] Database - -Database points to C:¥Java¥jakarta-tomcat-5.5.9¥webapps¥cocoo
n¥WEB-INF¥db

        magupi
        ring

Total documents: 2

C:¥Java¥xindice-1.1b4¥bin>

【リスト4:マグネットピアスの商品リスト(magupi.xml)】

<?xml version="1.0"?>
<productList category="マグネットピアス">
<product>
<name>マリンブルー丸プレートマグピ</name>
<id>35279</id>
<price>125</price>
<desc>全長約3.5cm</desc>
</product>
<product>
<name>穴あきフラワーマグピ</name>
<id>35329</id>
<price>125</price>
<desc>全長約4.5cm</desc>
</product>
<product>
<name>変形ハートマグピ</name>
<id>43518</id>
<price>180</price>
<desc>ハート約7×6mm</desc>
</product>
<product>
<name>6色スターセットマグピ</name>
<id>43731</id>
<price>170</price>
<desc>6色 6ペアセット 星約6mm</desc>
</product>
<product>
<name>ハイビスカスマグネットピアス</name>
<id>43878</id>
<price>170</price>
<desc>ハイビスカス約1.2cm</desc>
</product>
</productList>



【リスト5:リングの商品リスト(ring.xml)】

<?xml version="1.0"?>
<productList category="リング">
<product>
<name>赤いリンゴいっぱいリング</name>
<id>21982</id>
<price>180</price>
<desc>幅約6mm</desc>
<size>10</size><size>13</size>
<size>16</size>
</product>
<product>
<name>赤バラリング</name>
<id>24271</id>
<price>200</price>
<desc>バラ約1cm</desc>
<size>13</size><size>16</size>
</product>
<product>
<name>二連風リング</name>
<id>24292</id>
<price>105</price>
<desc>幅最大約1cm</desc>
<size>10</size><size>13</size>
<size>16</size>
</product>
<product>
<name>石付き赤ハートのプラリング</name>
<id>24304</id>
<price>100</price>
<desc>幅最大約1.5cm</desc>
<size>13</size><size>16</size>
</product>
<product>
<name>黄色系フルーツリング</name>
<id>24313</id>
<price>200</price>
<desc>チャーム全長約2.8cm</desc>
<size>10</size><size>16</size>
</product>
</productList>


XMLデータベースからドキュメント単位でデータを取り出す

ここまででXMLデータベースの準備ができたので、いよいよCocoonからXMLデータベースにアクセスしてデータを取り出してみることにしよう。まずは、登録したドキュメントをそのまま取り出し、整形してクライアントに返す方法を紹介する。

Cocoonディレクトリの下にサブディレクトリ「xmldbSample」を作成して、そこにXSLTスタイルシート(リスト 6)とサイトマップファイル(リスト 7)を配置しよう。

【リスト 6:XSLTスタイルシート(productList.xslt)】

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<head>
<title>アクセサリー商品リスト</title>
<style>
table { text-align : center }
tr.rowH { background : green; color : white }
tr { background : #CCFFCC }
span.id { font-size : smaller }
</style>
</head>
<body>
<h1>商品リスト</h1>
<table cellspacing="5">
<tr class="rowH">
<th>商品名<br/><span class="id">商品番号</span></th>
<th>説明</th>
<th>サイズ</th>
<th>価格(円)</th>
</tr>
<xsl:apply-templates/>
</table>
</body>
</html>
</xsl:template>

<xsl:template match="product">
<tr>
<td><xsl:value-of select="name"/><br/>
<span class="id">No.<xsl:value-of select="id"/></span></td>
<td><xsl:value-of select="desc"/></td>
<td><xsl:if test="size">
<xsl:for-each select="size">
<xsl:if test="position() != 1">
<xsl:text>, </xsl:text></xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:if></td>
<td><xsl:value-of select="price"/></td>
</tr>
</xsl:template>

</xsl:stylesheet>


【リスト 7:サイトマップファイル(sitemap.xmap)】

<?xml version="1.0" encoding="UTF-8"?>
<map:sitemap xmlns:map="<?xml:namespace prefix = map /><map:pipelines>http://apache.org/cocoon/sitemap/1.0">

<map:pipelines>
  <map:pipeline>

    <map:match pattern="*.html">
      <map:generate src="xmldb:xindice-embed:///db/accessories/{1}"/>
      <map:transform src="productList.xslt"/>
      <map:serialize/>
    </map:match>

    <map:match pattern="priceUnder150.xml">
      <map:generate src="xmldb:xindice-embed:///db/accessories/#//product[price &lt; 150]"/>
      <map:serialize type="xml"/>
    </map:match>

    <map:match pattern="priceUnder150">
      <map:generate src="xmldb:xindice-embed:///db/accessories/#//product[price &lt; 150]"/>
      <map:transform src="productList.xslt"/>
      <map:serialize/>
    </map:match>

  </map:pipeline>
</map:pipelines>

</map:sitemap>


XMLデータベースにアクセスするために新しいジェネレータを使う必要はなく、ファイルから読み込むのと同じようにしてアクセスできる。CocoonはXMLデータベースにアクセスするために「擬似プロトコル(pseudo protocol)」と呼ばれる機能を備えており、map:generate要素のsrc属性にXML:DB URLを使った指定を行うだけでXMLデータベースからのデータの取得ができるのだ。

ドキュメントをそのまま取り出すための指定はコレクションのURLのあとにスラッシュを入れ、続けてドキュメントキーを記述する。
<map:generate src="コレクションURL/ドキュメントキー"/>

コレクションのURLは、管理ツールの-cオプションに渡した文字列と同様であり、「xmldb:データベースID://ホスト名またはIPアドレス/コレクション名」という形になる。たとえば、コレクション「/db/accessories」に登録したドキュメントキー「ring」のXMLデータは次のように記述すれば取得できる。
<map:generate src="xmldb:xindice-embed:///db/accessories/ring"/>

さらに、リスト 7-①のように記述すれば、ドキュメントキーの後ろに「.html」を付けたURLでアクセスしてきたクライアントに、XMLデータベースから取得したXMLデータをXSLTで整形した結果を送ることができる。ブラウザからURL「http://localhost:8080/cocoon/xmldbSample/ring.html」にアクセスすれば、図 2のようにリングの商品リストを整形した結果が得られる。

XMLデータベースからXPathを使ってデータを取り出す

XMLデータベースを使うことの大きなメリットは、コレクション内の複数のXMLデータに対して同時に問い合わせを行い、その結果をまとめて取得できることだ。

単一のドキュメントを取り出す場合と同様に、XPathを使ったデータの問い合わせもサイトマップに指定するだけで実行可能だ。map:generate要素のsrc属性には、コレクションのURLのあとに「#」を入れ、続けてXPathを記述する。
<map:generate src="コレクションURL#XPath"/>

たとえば、コレクション「/db/accessories」に登録したドキュメントの中から価格150円未満の商品を取得したい場合、XPath「//product[price &lt; 150]」を使って次のように記述する7。
<map:generate src="xmldb:xindice-embed:///db/accessories/#//product[price &lt; 150]"/>

このXPathによる問い合わせの結果は複数のproduct要素から成るのだが、ジェネレータから返されるXMLデータはそれらの問い合わせ結果を1つにまとめたものとなる。サイトマップファイルにリスト 7-②のように記述して、まずXMLデータそのものがどのような形かを確認しよう。ブラウザから「http://localhost:8080/cocoon/xmldbSample/priceUnder150.xml」にアクセスして取得した結果は図 3のようになる。

取得結果全体はdb:results要素で囲まれ、個々の取得結果はdb:result要素(要素名末尾のsの有無に注意)で囲まれる。取得結果の中には複数のドキュメントからのデータが含まれるが、取得元のドキュメントキーがdb:result要素のdocid属性、および取得したデータ(この場合はproduct要素)のsrc:key属性に示される。

このデータをXSLTスタイルシートで整形すると、図 4の表示を得ることができる。マグネットピアスとリングの両方の商品リストから、150円未満の商品のみが取得できたことが確認できる。

まとめ

今回は、Cocoonに添付されたXMLデータベース「Xindice」にデータを格納して活用する方法を説明した。紙幅の関係で取り上げることができなかったが、XindiceはXMLデータを更新するための仕様「XUpdate(XML Update Language)」(http://xmldb-org.sourceforge.net/xupdate/)をサポートしており、Cocoonからデータベースに格納したXMLデータの更新を行うことができる。Cocoonに添付されたサンプルにXUpdateを使用したものがあるので、参考に見ていただくとよいだろう。

さらには、Xindiceではサポートされていないが多くのXMLデータベースでは「XQuery」(http://www.w3.org/XML/Query)という仕様に基づいたより複雑なデータ検索をもサポートしており、Cocoonと連携することも可能だ。興味のある方はぜひ試していただきたい8。

(太田 純)

Cocoonに添付されたXMLデータベースサンプル
Cocoonに含まれるXMLデータベースサンプルを動作させるには、http://localhost:8080/cocoon/にアクセスし、「samples」→「Block with samples」→「XML:DB Block」を順にクリックする。「XMLDB Block Samples」ページが開くので、まず「Init」をクリックしよう。これによってコレクション「cocoon」が作成され、XMLデータベースにアクセスする他の操作を行えるようになる。

サンプルのソースやサイトマップファイルはCocoonディレクトリの下のsamples¥blocks¥xmldbにあるので、参考にするとよいだろう。


図5:Cocoonに添付されたXMLDB Block Samples



この記事と関連の高い記事

関連キーワード:Apache


関連キーワード:XML


関連キーワード:cocoon




ページトップへ戻る