|
Last-modified: 2003-12-15 (月) 16:39:20 (7436d)
ネイティブXMLデータベース ~Xindice~2002.10.29
Jomora
はじめに さまざまな方面でXMLが利用されるようになり、その広まりとともに、XMLデータベースに対する注目も集まりつつあります。 リレーショナルか、それともXMLネイティブか 今後、ビジネスでやりとりされる文書は、ますますXML化されていくでしょう。大量のXML文書の保存と管理のために、XML対応のデータベースが必須となります。
どちらも一長一短がある、というのが現状です。DB選択の際には、それぞれの特徴を考えて、要求に合う方を選ぶ必要があります。 XML対応のリレーショナルデータベースXML対応のリレーショナルデータベースは、XML文書をリレーショナル形式にマッピングして保存します。つまり、XML文書の決められた部分を特定のテーブルの特定のフィールドのデータにマッピングすることで、XML文書の中のデータをデータベースに格納するのです。当然、データベースに格納されているデータをXML文書に組み立てて出力する機能も持ちます。 この方式の特徴は、まさにこの「XML要素を抜き出して保存する」点にあります。
とはいえ、定型のXML文書を扱うだけならば、実績、信頼性、データベースとしての機能の優位性という面で、リレーショナルデータベースを選択するメリットは大きいといえます。 ネイティブXMLデータベース XMLの階層構造や、名前空間等の付加情報が複雑な場合には、ネイティブXMLデータベースを選択すべきかもしれません。 この方式の特徴は、XML文書の特徴を生かした管理ができることにあります。
しかし、デメリットもあります。
これらの特徴を踏まえた上で、実際にネイティブXMLデータベースの機能と動作を見ていきましょう。 XindiceXindice(イタリア語風で『ジンディーチェ(zeen-dee-chay)』と呼ぶらしい)は、The Apache XML Projectの1つとして開発されているオープンソースのネイティブXMLデータベースです。Javaで実装されています。固有の特徴としては、
ということがあります。まずは、簡単に使って見ましょう。 インストールそれでは、Windows上でXindiceのインストールをします。 XindiceはJava環境下で動作します。まず、JDK1.3をインストールしてください。JDK1.4を使う際には、JDKに付属するXercesとXalanを無効にする必要があります。JDK1.2以前では動作しません。そして、環境変数の設定をしてください。Xindiceの起動スクリプト内に記述してもかまいませんが、OSの設定で変更しまった方がクライアントにも適応されるので簡単です。JDKをC:\jdk1.3.1_06にインストールしたとすると、 JDKの環境設定(JAVA_HOME, PATH) > JAVA_HOME=C:\jdk1.3.1_06 > PATH=%PATH%;%JAVA_HOME%\bin XindiceのWebページから実行ファイル(xml-xindice-1.0.zip)をダウンロードします。現在のバージョンは1.0です。ダウンロードしたファイルを解凍すると、xml-xindice-1.0 というフォルダができます。次に、環境変数の設定をします。C:\xml-xindice-1.0 に解凍したとすると、 Xindiceの環境設定(XINDICE_HOME, PATH) > XINDICE_HOME=C:\xml-xindice-1.0 > PATH=%PATH%;%XINDICE_HOME%\bin 以上で、インストールは完了です。 起動と停止Xindiceの起動 > %XINDICE_HOME%startup.bat 正常に起動した際には、次のようなメッセージが出力されます。db はデフォルトで作成されるデータベースインスタンスです。 C:\xml-xindice-1.0>startup.bat java -classpath … -noverify org.apache.xindice.core.server.Xindice C:\xml- xindice-1.0\config\system.xml Xindice 1.0 (Birthday) Database: 'db' initializing Script: 'GET' added to script storage Service: 'db' started Service: 'HTTPServer' started @ http://hostname:4080/ Service: 'APIService' started Server Running Xindiceの終了 > xindiceadmin shutdown -c /db コマンドラインからの操作まずはコマンドラインからデータベースを操作してみましょう。登録データとして次の2つのXMLファイルを準備します。 <?xml version="1.0" encoding="Shift_JIS" ?> <diary year="2002" month="09"> <date day="08"> <item>一日中、部屋と押入れの整頓に費やす。 9月中に<a href="http://www.bidders.co.jp/bpu/1310605">オークション</a>かなんかで、要らないものが処分できたらいいなぁ…。 MDプレイヤーとか、もう要らないよなぁ…。</item> </date> </diary> <?xml version="1.0" encoding="Shift_JIS" ?> <diary year="2002" month="08"> <date day="14"> <item>今日は朝から、帰省移動。 4時間ぐらいかかるんですよ、電車で…。 途中、乗り換えもあって、ずっと寝ていられないし…。</item> </date> <date day="15"> <item>今日は、有給充当日。 「自主的に有給とってね」の日です。 なんか、納得いかないんですけど… (^^;;</item> <item><a href="http://www.town.fukumitsu.toyama.jp/">私の田舎のWebサイト</a>も、結構こってました(++) イベント・施設情報が検索できたり、町民の意見交換用の掲示板とか…。 なかなかよろしいんじゃないでしょうか? <a href="http://www.e-fuku3.com/">ユビキタウンふくみつ</a>なんてポータルサイトもあったりして…。 でも、Java使ってるらしく、ページ遷移が遅いなぁ、と思うのは私だけ?</item> </date> </diary> Xindiceでは、XML文書を「コレクション」と「ドキュメント」という単位で管理します。ちょうど、ファイルシステムで言うところの「ディレクトリ」と「ファイル」の関係に相当します。同じような階層構造を成します。 まず、db に新規のコレクションを作成します。名前をsampledbとします。 コレクションの追加 > xindiceadmin ac -c /db -n sampledb Created : /db/sampledb このコレクションに、先ほどの2つのXML文書を、それぞれsam01、sam02というキーに関連付けて、追加します。 ドキュメントの追加 > xindiceadmin ad -c /db/sampledb -f sample01.xml -n sam01 Added document /db/sampledb/sam01 > xindiceadmin ad -c /db/sampledb -f sample02.xml -n sam02 Added document /db/sampledb/sam02 では、これらのドキュメントを検索してみましょう。検索条件はXPathで指定します。 検索 > xindiceadmin xpath -c /db/sampledb -q "//item" <?xml version="1.0"?> <item xmlns:src="http://xml.apache.org/xindice/Query" src:col="/db/sampledb" src:key="sam01"> 一日中、部屋と押入れの整頓に費やす。 9月中に<a href="http://www.bidders.co.jp/bpu/1310605">オークション</a>かなんかで、要らないものが処分できたらいいなぁ…。 MDプレイヤーとか、もう要らないよなぁ…。</item> <?xml version="1.0"?> <item xmlns:src="http://xml.apache.org/xindice/Query" src:col="/db/sampledb" src:key="sam02">今日は朝から、帰省移動。 4時間ぐらいかかるんですよ、電車で…。 途中、乗り換えもあって、ずっと寝ていられないし…。</item> <?xml version="1.0"?> <item xmlns:src="http://xml.apache.org/xindice/Query" src:col="/db/sampledb" src:key="sam02">今日は、有給充当日。 「自主的に有給とってね」の日です。 なんか、納得いかないんですけど… (^^;;</item> <?xml version="1.0"?> <item xmlns:src="http://xml.apache.org/xindice/Query" src:col="/db/sampledb" src:key="sam02"> <a href="http://www.town.fukumitsu.toyama.jp/">私の田舎のWebサイト</a>も、結構こってました(++) イベント・施設情報が検索できたり、町民の意見交換用の掲示板とか…。 なかなかよろしいんじゃないでしょうか? <a href="http://www.e-fuku3.com/">ユビキタウンふくみつ</a>なんてポータルサイトもあったりして…。 でも、Java使ってるらしく、ページ遷移が遅いなぁ、と思うのは私だけ?</item> 検索結果が1件ずつ、XMLドキュメントの形で戻ってきます。 [補足] 私の環境では、"//date[@day='08']" のような書式のXPath指定をコマンドラインで実行すると、『使い方が誤っています。』と言われます。コマンドプロンプトの問題でしょうか。アプリケーションからの検索では、この書式も問題ありません。 その他の主なコマンドは下記の通りです。 コレクションのリスト表示 xindice lc -c {ベースとなるコレクション} コレクションの削除 xindiceadmin dc -c {ベースとなるコレクション} -n {削除するコレクションの名前} ドキュメントのリスト表示 xindice ld -c {ベースとなるコレクション} ドキュメントの取得 xindice rd -c {ベースとなるコレクション} -n {ドキュメントのキー} -f {書き出すファイル名} ドキュメントの削除 xindice dd -c {ベースとなるコレクション} -n {ドキュメントのキー} ちなみに、DBからドキュメントを取得するとわかるのですが、ドキュメントの文字コードは全てUTF-8に変換されています。 Javaプログラムからの利用(検索処理)Xindiceの検索用APIは、JDBCドライバのような形で提供されています。DBクライアントプログラムの実行には、%XINDICE_HOME%java\lib 以下の、xmldb.jar、xindice.jar、openorb-1.2.0.jar、xalan-2.0.1.jar、xerces-1.4.3.jar をJavaのクラスパスに追加する必要があります。 XPath検索に使うプログラムのサンプルを下記に示し、解説していきます。 検索サンプルプログラム 01. try { 02. String driver = "org.apache.xindice.client.xmldb.DatabaseImpl"; 03. Class c = Class.forName(driver); 04. 05. org.xmldb.api.base.Database database = 06. (org.xmldb.api.base.Database)c.newInstance(); 07. org.xmldb.api.DatabaseManager.registerDatabase(database); 08. 09. org.xmldb.api.base.Collection col = 10. org.xmldb.api.DatabaseManager.getCollection 11. ("xmldb:xindice://localhost:4080/db/sampledb"); 12. 13. org.xmldb.api.modules.XPathQueryService service = 14. (org.xmldb.api.modules.XPathQueryService) 15. col.getService("XPathQueryService", "1.0"); 16. 17. String xpath = "//date[@day='14']/item"; 18. org.xmldb.api.base.ResourceSet resultSet = service.query(xpath); 19. 20. // イテレータの取得 21. org.xmldb.api.base.ResourceIterator results = resultSet.getIterator(); 22. // リソースがある間、繰り返す 23. while (results.hasMoreResources()) { 24. // 次のリソースを取得 25. org.xmldb.api.base.Resource res = results.nextResource(); 26. // ResourceがXMLResourceかどうかの確認 27. if (res.getResourceType().equals("XMLResource")) { 28. // 内容を文字列として表示 29. System.out.println((String)res.getContent()); 30. // DOMとして内容を取得 31. org.xmldb.api.modules.XMLResource xmlres = 32. (org.xmldb.api.modules.XMLResource)res; 33. org.w3c.dom.Document document = 34. (org.w3c.dom.Document)xmlres.getContentAsDOM(); 35. // documentに対する処理を行う 36. document = (org.w3c.dom.Document)clean(document); 37. NodeList nl = document.getFirstChild().getChildNodes(); 38. for (int i = 0; i < nl.getLength(); i++) { 39. System.out.println("item[" + i + "] = " 40. + nl.item(i).getFirstChild().getNodeValue()); 41. } 42. } else { 43. System.out.println("not XMLResource"); 44. } 45. } 46. } catch (XMLDBException ex) { 47. ex.printStackTrace(); 48. } catch (InstantiationException ex) { 49. ex.printStackTrace(); 50. } catch (IllegalAccessException ex) { 51. ex.printStackTrace(); 52. } catch (ClassNotFoundException ex) { 53. ex.printStackTrace(); 54. } finally { 55. if (col != null) { 56. col.close(); 57. } 58. } 02~07行目: 09~11行目: 13~15行目: 17~18行目: 20~21行目: 22~45行目: public static Node clean(Node node) { if (node.hasChildNodes()) { Node childnode = node.getFirstChild(); while (childnode != null) { if (childnode.getNodeType() == Node.TEXT_NODE && childnode.getNodeValue().trim().length() == 0) { Node delnode = childnode; childnode = childnode.getNextSibling(); node.removeChild(delnode); } else { if (childnode.hasChildNodes()) { clean(childnode); } childnode = childnode.getNextSibling(); } } } return node; } 56行目: 以上で、基本的な参照方法の説明は終わりですが、%XINDICE_HOME%\java\example には、非常に興味深いサンプルがありますので、是非ご参照下さい。 XUpdate 次に、XMLデータの追加・更新・削除を行います。Xindiceでは、データの追加・更新・削除を行うためにXUpdateという言語を採用しています。XUpdateは、XML:DB Initiativeが開発したXML-DB用の言語仕様で、XUpdateのページにワーキングドラフト仕様が公開されています。 XMLデータの追加 XMLデータの追加プログラムのサンプルを示し、解説していきます XMLデータ追加サンプルプログラム 01. try { 02. String driver = "org.apache.xindice.client.xmldb.DatabaseImpl"; 03. Class c = Class.forName(driver); 04. 05. org.xmldb.api.base.Database database = 06. (org.xmldb.api.base.Database)c.newInstance(); 07. org.xmldb.api.DatabaseManager.registerDatabase(database); 08. 09. col = org.xmldb.api.DatabaseManager.getCollection 10. ("xmldb:xindice://localhost:4080/db/sampledb"); 11. 12. // XUpdateQueryServiceの取得 13. org.xmldb.api.modules.XUpdateQueryService service = 14. (org.xmldb.api.modules.XUpdateQueryService) 15. col.getService("XUpdateQueryService", "1.0"); 16. 17. String xupdate; 18. xupdate = "<xupdate:modifications version=\"1.0\" " 19. + "xmlns:xupdate=\"http://www.xmldb.org/xupdate\">" 20. + "<xupdate:append " 21. + "select=\"/diary/date[@day='08']\" child=\"last()\">" 22. + "<item sam=\"test\">sample</item>" 23. + "</xupdate:append>" 24. + "</xupdate:modifications>"; 25. long num = service.update(xupdate); 26. } catch (InstantiationException ex) { 27. ex.printStackTrace(); 28. } catch (IllegalAccessException ex) { 29. ex.printStackTrace(); 30. } catch (ClassNotFoundException ex) { 31. ex.printStackTrace(); 32. } catch (XMLDBException ex) { 33. ex.printStackTrace(); 34. } finally { 35. if (col != null) { 36. col.close(); 37. } 38. } 02~10行目: 12~15行目: 17~23行目: 24行目: 実は、追加・挿入するXMLデータの要素、属性に日本語テキストがあると、 org.omg.CORBA.DATA_CONVERSION: minor code: 1398079494 completed: No というエラーが表示されて追加できません。いろいろ文字コード変換してみましたが、うまく動かないようです。Xindice1.0のXUpdate実装は、日本語未サポートということのようですね。 XMLデータの追加の方法は、他にもあります。以下に紹介します。 XMLデータの追加(2)下記の xupdate:insert-after を使ったXUpdate構文でも、上記 xupdate:append と同じ動作となります。 xupdate:insert-after <xupdate:modifications version="1.0" xmlns:xupdate="http://www.xmldb.org/xupdate"> <xupdate:insert-after select="/diary/date[@day='08']/item[last()]"> <item sam="test">sample</item> </xupdate:insert-after> </xupdate:modifications> XMLデータの追加(3)xupdate:insert-before の動作も、名前から推して知るべしです。 xupdate:insert-before <xupdate:modifications version="1.0" xmlns:xupdate="http://www.xmldb.org/xupdate"> <xupdate:insert-before select="/diary/date[@day='08']/item[position()='1']"> <item sam="sample">test</item> </xupdate:insert-before> </xupdate:modifications> XMLデータの更新xupdate:update は、文字列の更新をします。「ノードセットの置き換え」はできません。その際には、後で説明するxupdate:removeとxupdate:insert-afterを使って、「削除して追加する」必要があります。 xupdate:update <xupdate:modifications version="1.0" xmlns:xupdate="http://www.xmldb.org/xupdate"> <xupdate:update select="/diary/date[@day='08']/item[last()]/@sam"> sample1 </xupdate:update> </xupdate:modifications> XMLデータの削除xupdate:remove は、ノードの削除をします。 xupdate:remove <xupdate:modifications version="1.0" xmlns:xupdate="http://www.xmldb.org/xupdate"> <xupdate:update select="/diary/date[@day='08']/item[last()]" /> </xupdate:modifications> その他のインストラクション xupdate:rename は、ノード名を変更します。 これらは、XUpdate仕様に記述されていますが、Xindice1.0の実装は不完全なようです。 インデックスの指定リレーショナルデータベースでも必ずといっていいほど利用されるインデックスの管理についてです。管理コマンドを説明します。 インデックスのリスト表示 xindiceadmin li -c {コレクション} インデックスの追加 xindiceadmin ai -c {コレクション} -n {インデックス名} -p {パターン} パターンはXPath指定です。 xindiceadmin di -c {コレクション} -n {インデックス名} インデックスをつけると、ドキュメント数の増加に伴う参照時間の増加を抑えられます。ほぼ、リレーショナルデータベースと同じ感覚です。 Xindiceについての補足プログラムからColectionの管理を行うには、CollelctionManager を使う。 おわりに 今回の調査で目に付いたのは、Xindiceの日本語対応の不備です。まだまだ日本語圏で使えるレベルではないようですね。XMLといえばUCSから生まれたUTF-8を標準としていることからもわかるように、国際化を主眼の一つとしているはずです。XML-DBには、ぜひともmulti-language対応となって欲しいものです。 今後も各方面でのXMLの普及に伴い、XMLデータをスムーズに利用、ストアする必要性は間違いなく高まるでしょう。そのシステムに合った設計を見極め、XML-DBをうまく使えるようなエンジニアが求められるようになるかもしれません。そういう人材が希少な今がチャンスかもしれませんね。 |