SAXでXML文書処理

XMLをJavaで処理するとなると普通はDOMを使いましょう、となります。実際DOMはXMLをハンドリングする機能が充分に用意されているので、通常はこれで良いとなるのですが、扱うXML文書のサイズや数が増えてくるとDOMの弱点であるオブジェクトサイズの大きさがネックになるケースが出てきます。

そんな時に登場するのがSAXです。DOMはW3Cで標準化が行われていますが、SAXはXML-DEVメイリングリストのメンバーが中心となってsaxproject.orgを創り、仕様作成が行われています。標準化団体が技術的志向(ないしは政治的要因)で分裂したり、けんかしたり、というのは珍しくない現象ですが、DOMとSAXは今のところ敵対関係にあるというのではなく、相互補完している形になっています。それぞれに適切な分野があるでしょう、という処ですね。

JavaでSAXの機能を利用するのは簡単です。SAXのAPI仕様はJDK1.4.0をインストールすればorg.xml.sax以下のパッケージに入ってきますし、パーザはApacheプロジェクトで開発されているXerces-Jのものを使うことができます。以下でSAX使い方を見てみましょう。

SAXを使うときはイベント駆動(Event Driven)型と呼ばれる構造のプログラムを作成することになります。XML文書を前から読んでゆき、タグ構造が見つかったときに、適当なハンドラが呼び出される、というものです。XML文書を読んでハンドラを呼び出す部分はSAXで用意されるので、呼び出されるハンドラを作成することになります。

単純にXML文書を読み込み、適当な値を標準出力に出力するプログラムを作成してみます。ハンドラはゼロから作るのではなく、org.xml.sax.helpers.DefaultHandlerをextendsすることになります。

/**
 * SAXプログラムサンプルクラス
 */
public SaxSample extends org.xml.sax.helpers.DefaultHandler {
	/**
	 * コンストラクタ
	 */
	public SaxSample () {
		// DefaultHandlerのコンストラクタを呼ぶ
		super();
	}

XMLファイルを読み出す部分はorg.xml.sax.helpers.XMLReaderFactoryクラスを用いて、XMLReaderクラスを作成します。ここではXerces-JのSAXパーザを明示的に指定しています。

	:
	public static main(String[] args) {
		org.xml.sax.XMLReader reader
			= org.xml.sax.helpers.XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");

そして、このXMLReaderに対してハンドラの登録を行います。ContentHandlerとErrorHandlerとして作成したクラスのオブジェクトを登録する場合には、

		SaxSample myHandler = new SaxSample();
		reader.setContentHandler(myHandler);
		reader.setErrorHandler(myHandler);
というコードを入れます。org.xml.sax.DefaultHandlerはorg.xml.sax.ContentHander、org.sax.xml.ErrorHandlerのいずれもimplementsしていますので、ContentHander、ErrorHandlerのいずれとしても登録できます。さらには、org.xml.sax.DTDHanderもimplementsしていますので、必要なものは揃っている状態です。

あとはファイルを指定してXMLReaderに読ませれば良いので、引数でXMLファイルを指定したとすると、

		for (int i = 0; i < args.length; i++) {
			java.io.FileReader fr = new java.io.FileReader(args[i]);
			reader.parse(new org.xml.sax.InputSource(fr));
		}
でOKです。とはいってもこれではXMLファイルを読むだけで何もしない状態ですので、イベントハンドラを作成してゆく必要があります。どのようなイベントに対してどのようなハンドラがあるのかは、org.xml.sax.ContentsHandlerのメソッドを見ると判ります。例えばXML文書の先頭ではstartDocument()メソッドが呼ばれますし、XML文書の終わりに達するとendDocument()メソッドが呼ばれます。タグが書かれている処に来るとstartElement()メソッドが呼ばれ、終了タグに来るとendElement()が呼ばれる、といった具合です。タグ以外のデータそのものはcharacters()メソッドで処理することができます。

またXML文書を読んでいて文法上の問題が発生すると、警告、回復可能なエラー、回復不能のエラーに対しそれぞれErrorHandlerのwarning()、error()、fatalError()の各メソッドが呼び出されますので、これらのメソッドを定義して必要なエラー処理を行います。また記法や解釈できないEntityの情報を処理するにはDTDHandlerの各メソッドを作成します。

以下にサンプルをつけますので、参照ください。

SaxSample.java

XMLファイルを読み出す部分(つまりはSAXパーサを呼び出す部分になりますが)は JAXP(今はJDKに含まれましたが)ではXMLReaderとは別の方法が提供されています。

	javax.xml.psersers.SAXParserFactory factory =
		javax.xml.parsers.SAXParserFactory.newInstance();
	javax.xml.psersers.SAXParser parser =
		factory.newSAXParser();
としてSAXParserのインスタンスを取得し、SAXParser#parseメソッドを呼び出す方法です。SAXParserはXMLReaderをラップしていると書いてある通り、SAXParser#parse()内部で XMLReaderを作成して、そのparse()を呼び出しています。ハンドラ等は上記で説明した ものと同じで良いのですが、パーザを明示的に指定することはできずCrimsonのものが 使われるという点に注意が必要です。


人材開発室 PoisonSoft