XMLDB.jp

XMLDB開発支援
HOME  >  XMLDB開発支援  >  XML2CSVで学ぶ実践的なXprioriプログラミング 第2回

XML2CSVで学ぶ実践的なXprioriプログラミング 第2回

第2回:XML2CSVのソースコードを読解する(1)
2006年4月20日 更新


RDB(リレーショナルデータベース)プログラミングの経験者にとって、RDBプログラミングはある程度型どおりのステップで行われるもの、と感じられるはずだ。まずRDBとの接続を作り、SQLクエリを発行する。そして、検索の場合は、結果をプログラム上で扱いやすいようにオブジェクトにマッピングする。こうした流れが頭の中にあるから、プログラミングをしていても迷いを感じることはない。XML DBプログラミングの場合にも、同じように一連の流れが存在する。


ここでは、Xprioriと連携する実際のアプリケーションから、XML DBでとられる一連のプログラミングステップを学びとることにしよう。取り上げるのは、データベースに格納されたXML文書をCSV形式に変換するツール、XML2CSVだ。XML2CSVのソースコードから、使えるXML DBプログラミングのテクニックを盗んでほしい。




Xprioriへの接続、クエリの実行

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;
      }
  }
▲データベースへの接続(mki.xml2csv.access.NeoCoreAccessクラス)

次に、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データ
▲com.neocore.httpclient.NeoConnectionクラスのメソッド

XMLデータをデータベース上に作成する処理は、次の通りだ。


public String storeXML(String storeXml) {
    String str = null;
    try {
        str = neo.storeXML(sessionId, storeXml, "", "");
    } catch (Exception e) {
        ...中略...
    }
    return str;
▲XMLデータの作成(mki.xml2csv.access.NeoCoreAccessクラス)

データベース上の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データの更新(mki.xml2csv.access.Xml2CsvNeoCoreAccessクラス)

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データの削除(mki.xml2csv.access.Xml2CsvNeoCoreAccessクラス)

最後に、次のようにしてXMLデータの問い合わせをおこなう。


public String queryXML(String query) {
    String result = null;
    try {
        result = neo.queryXML(sessionId, query);
        return result;
    } catch (Exception e) {
        return result;
    }
}
▲XMLデータの問い合わせ(mki.xml2csv.access.NeoCoreAccessクラス)

XML2CSVでは、上記のデータベースとの接続やクエリの実行を行う部分は、Xml2CsvNeoCoreAccessクラス(とその上位クラス)に一箇所にまとめられている。データソースとのやり取りを一手に引き受けるクラスによって、NeoCore API利用の詳細が隠蔽されているのだ。


このクラスはDAO(データアクセスオブジェクト)などと呼ばれるもので、データベースプログラミングでは一般的な設計方法である。DAOによってデータソース固有の実装部分が隠蔽されるため、アプリケーションの他の部分が固有のデータソースに依存しなくて済むようになる。こうしたRDBプログラミングでは定石の設計ノウハウは、XML DBプログラミングにおいても有効だ。


XMLデータをオブジェクトに変換(O/Xマッピング)

データベースから結果を受け取ったときは、なんらかの形でそのXMLデータを利用することになる。XMLデータをテキストのまま扱うのは、行う処理が複雑になればなるほど大変だ。そこで、XMLデータをオブジェクトの形に変換することが重要になる。


RDBプログラミングで「O/R(Object / Relational)マッピング」と呼ばれるステップと同じである。RDBプログラミングでは、2次元の表形式のデータをオブジェクトの世界で扱いやすくするために、表からオブジェクトへの変換を行う。Hibernate(http://www.hibernate.org/)など、O/Rマッピングのための専用フレームワークがある。


xml2csv2-1.gif
▲O/Rマッピング


一方、XML DBプログラミングで必要となるのは、いわば「O/X(Object / XML)マッピング」と呼べるステップだ。このステップは、「データバインディング」と呼ばれることもある。


xml2csv2-2.gif
▲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;
  }
}
▲XML2CSVのO/Xマッピング(mki.xml2csv.access.Xml2CsvConfigXmlParseクラス)

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;
}
▲XMLデータをDOMの文書オブジェクトに変換(mki.xml2csv.access.DomAccessクラス)

ここでは、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) {
    ...中略...
  }
}
▲DOMの文書オブジェクトから通常のJavaオブジェクトへマッピング
  (mki.xml2csv.access.Xml2CsvConfigXmlParseクラス)

文書オブジェクトの形になった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を自動生成する、という少しアドバンストな内容に迫ってみたい。



制作協力:WINGSプロジェクトwingslogo.gif  

▲このページのTOPへ

  • 無償で使える!XMLDB「NeoCore」
  • サイバーテック求人情報
  • メールマガジン申し込み
  • TEchScore

  • ▲NeoCoreについて記載されています!

  • ▲XMLマスター教則本です。試験対策はこれでばっちり!
Copyright (c) CyberTech corporation ltd. All ights Reserved. | サイバーテックについて | ご利用ガイド