mb_language("uni"); mb_internal_encoding("utf-8"); mb_http_input("auto"); mb_http_output("utf-8"); ?>
RDB(リレーショナルデータベース)プログラミングの経験者にとって、RDBプログラミングはある程度型どおりのステップで行われるもの、と感じられるはずだ。まずRDBとの接続を作り、SQLクエリを発行する。そして、検索の場合は、結果をプログラム上で扱いやすいようにオブジェクトにマッピングする。こうした流れが頭の中にあるから、プログラミングをしていても迷いを感じることはない。XML DBプログラミングの場合にも、同じように一連の流れが存在する。
ここでは、Xprioriと連携する実際のアプリケーションから、XML DBでとられる一連のプログラミングステップを学びとることにしよう。取り上げるのは、データベースに格納されたXML文書をCSV形式に変換するツール、XML2CSVだ。XML2CSVのソースコードから、使えるXML DBプログラミングのテクニックを盗んでほしい。
RDBもXML DBも、どちらも同じくデータベースシステムだ。そのため、データベースに接続し、データを更新したり参照したりする、というところまでは変わりがない。XML2CSVでは、Xprioriが提供するNeoCore APIを使ってこれらを実装している。
NeoCore APIは、クライアントプログラムがXprioriと連携するために用意されているライブラリである。Xprioriインストールフォルダ下の「API\Java\lib\xmlsclient.jar」にある。APIを利用するには、このjarファイルをクラスパスに通せばよい。
まず、XML2CSVのデータベースへの接続部分を見てみよう。com.neocore.httpclient.NeoConnectionクラスを使って、データベースとの接続を確立する。なお前回も紹介したように、接続プーリングなど本格的な機能を使いたいときは、NeoConnectionクラスの代わりにcom.neocore.httpclient.SessionManagedNeoConnectionクラスを使う方がよい。
protected NeoConnection neo = null; ...中略... protected String sessionId = null; /** * コンストラクタ * * @param host ホスト * @param port ポート番号 * @param userid ログインユーザID * @param password パスワード * @throws Exception */ public NeoCoreAccess( String host, int port, String userid, String password) throws Exception { try { //NeoCoreサーバにログイン if (neo == null) { neo = new NeoConnection(host, port); sessionId = neo.login(userid, password); } } catch (Exception e) { ...中略... throw e; } } |
次に、XMLデータの作成/更新/削除や問い合わせを行う部分だ。先ほどのNeoConnectionクラスに用意されている次のメソッドを使う(SessionManagedNeoConnectionクラスにも同様のメソッドがある)。
メソッド |
用途 |
パラメータの説明 |
storeXML(String sid, String source, String schema, String prefix) |
XMLデータの作成 | sid - セッションID source - データベース上に作成するXMLデータ schema - XMLスキーマの参照名 prefix - 作成するXMLデータのメタデータ 戻り値 - XML形式の成功メッセージ |
modifyXML(String sid, String query, String modifyXML) |
XMLデータの更新 | sid - セッションID query - 変更対象を指定するXPath式 modifyXML - 新たに書き換えるXMLデータ 戻り値 - 変更された総ノード数を示すXML |
deleteXML(String sid, String query) |
XMLデータの削除 | sid - セッションID query - 削除対象を指定するXPath式 戻り値 - 削除された総ノード数を示すXML |
queryXML(String sid, String query) |
XMLデータの 問い合わせ |
sid - セッションID query - XPath式による問い合わせ 戻り値 - 問い合わせ結果を含むXMLデータ |
XMLデータをデータベース上に作成する処理は、次の通りだ。
public String storeXML(String storeXml) { String str = null; try { str = neo.storeXML(sessionId, storeXml, "", ""); } catch (Exception e) { ...中略... } return str; |
データベース上のXMLデータ更新は、次のようにしている。
public String modifyConfigXML(String id, String modfyXml) { String str = null; String query = getConfigQuery(id); try { str = neo.modifyXML(sessionId, query, modfyXml); } catch (Exception e) { ...中略... } return str; } |
XMLデータの削除を行うコードは、以下の通りだ。
public String deleteConfigXML(String id) { String str = null; String query = getConfigQuery(id); try { str = neo.deleteXML(sessionId, query); } catch (Exception e) { ...中略... } return str; } |
最後に、次のようにしてXMLデータの問い合わせをおこなう。
public String queryXML(String query) { String result = null; try { result = neo.queryXML(sessionId, query); return result; } catch (Exception e) { return result; } } |
XML2CSVでは、上記のデータベースとの接続やクエリの実行を行う部分は、Xml2CsvNeoCoreAccessクラス(とその上位クラス)に一箇所にまとめられている。データソースとのやり取りを一手に引き受けるクラスによって、NeoCore API利用の詳細が隠蔽されているのだ。
このクラスはDAO(データアクセスオブジェクト)などと呼ばれるもので、データベースプログラミングでは一般的な設計方法である。DAOによってデータソース固有の実装部分が隠蔽されるため、アプリケーションの他の部分が固有のデータソースに依存しなくて済むようになる。こうしたRDBプログラミングでは定石の設計ノウハウは、XML DBプログラミングにおいても有効だ。
データベースから結果を受け取ったときは、なんらかの形でそのXMLデータを利用することになる。XMLデータをテキストのまま扱うのは、行う処理が複雑になればなるほど大変だ。そこで、XMLデータをオブジェクトの形に変換することが重要になる。
RDBプログラミングで「O/R(Object / Relational)マッピング」と呼ばれるステップと同じである。RDBプログラミングでは、2次元の表形式のデータをオブジェクトの世界で扱いやすくするために、表からオブジェクトへの変換を行う。Hibernate(http://www.hibernate.org/)など、O/Rマッピングのための専用フレームワークがある。
▲O/Rマッピング
一方、XML DBプログラミングで必要となるのは、いわば「O/X(Object / XML)マッピング」と呼べるステップだ。このステップは、「データバインディング」と呼ばれることもある。
▲O/Xマッピング
XML2CSVでは、O/XマッピングにJava標準のDOM APIを使っている。XML2CSVがどうやってXMLデータをオブジェクトに変換しているかを見てみよう。以下が、そのソースコードだ。細かいところは気にせず、マッピングの大枠を概観してほしい。
private DomAccess dom = null; ...中略... public Xml2CsvConfigModel parseString(String data, String enc) throws Exception { Xml2CsvConfigModel model = null; try { //定義情報読み込み Document doc = dom.parseString(data, enc); model = getConfigModel(doc); return model; } catch (Exception e) { throw e; } } |
DomAccessクラスはXML2CSV内部のクラスで、DOM APIを簡単に扱えるようにしたユーティリティクラスだ。テキストとして受け取ったXMLデータを、DomAccessクラスを使ってDOMの文書オブジェクトに変換する。そして、その文書オブジェクトからデータをXml2CsvConfigModelオブジェクトにマッピングする。Xml2CsvConfigオブジェクトが、読み込んだXMLデータの最終的なオブジェクト表現であり、XML2CSVでは、O/XマッピングはXMLデータからXml2CsvConfigModelオブジェクトへのマッピングを意味する。
XMLデータをDOMの文書オブジェクトに変換するところを、詳しく見ていこう。
private DocumentBuilderFactory dbfactory = null; private DocumentBuilder builder = null; ...中略... public Document parseString(String str, String enc) { Document doc = null; try { //取得したXMLをinputStreamに変換 ByteArrayOutputStream baosIn = new ByteArrayOutputStream(); baosIn.write(str.getBytes(enc)); inputStream is = new ByteArrayinputStream(baosIn.toByteArray()); doc = parseStream(is); } catch (Exception e) { ...中略... } return doc; } ...中略... public Document parseStream(inputStream is) { Document doc = null; try { doc = builder.parse(is); } catch (Exception e) { ...中略... } return doc; } |
ここでは、DOM APIのjavax.xml.parsers.DocumentBuilderクラスが使われる。DocumentBuilder#parseメソッドを使って、入力ストリームから文書オブジェクトを構築するのが、DOMプログラミングの基本だ。
最後に、DOMの文書オブジェクトのデータをXml2CsvConfigModelオブジェクトにマッピングする箇所を読みとこう。
private Xml2CsvConfigModel getConfigModel(Document doc) throws Exception { Xml2CsvConfigModel model = null; String tmp = null; //定義情報読み込み try { model = new Xml2CsvConfigModel(); Element elmDefine = doc.getDocumentElement(); //ID NodeList lstNode = elmDefine.getElementsByTagName("config"); Element elm = (Element) lstNode.item(0); model.setId(elm.getAttribute("id")); //ホスト model.setHost(getTagValue(elmDefine, "host")); //ポート String str = getTagValue(elmDefine, "port"); model.setPort(str); //ユーザID model.setUserid(getTagValue(elmDefine, "userid")); //パスワード model.setPassword(getTagValue(elmDefine, "password")); ...中略... return model; } catch (Exception e) { ...中略... } } |
文書オブジェクトの形になったXMLデータから、必要なデータをひとつひとつ読み込んでXml2CsvConfigModelオブジェクトのsetterメソッドに渡している。
DOM APIを使った場合の、O/Xマッピングの流れをまとめよう。基本的に次の2つの手順で行う。
1. テキストのXMLデータを、DocumentBuilderを使ってDOMの文書オブジェクトにする
2. DOMの文書オブジェクトから、目的のオブジェクトにデータをセットする
O/Xマッピングの実現方法は、DOM以外にもある。XMLデータは単に読み込むだけでいいので、SAX APIを使ってもいいだろう。DOMやSAXのような汎用APIだけでなく、XMLとJavaオブジェクトとのデータ変換に特化したライブラリもある。
JAXB(Java Architecture for XML Binding, http://java.sun.com/webservices/jaxb/)やApache JakartaのCommons Betwixt(http://jakarta.apache.org/commons/betwixt/)、Commons Digester(http://jakarta.apache.org/commons/digester/)などだ。これらは、まさしくO/Xマッピングのライブラリと言ってもいいだろう。
以上、XML2CSVのソースコードから、XML DBプログラミングの基本的な部分を見てきた。XML DBプログラミングにおいても、RDBの場合と同様、ある程度決まったステップがあること、また、設計ノウハウの多くがXML DBでも有効なことを理解していただけただろう。
次回も、引き続きXML2CSVのソースコードを読むことにする。XQueryを自動生成する、という少しアドバンストな内容に迫ってみたい。
▲このページのTOPへ