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.javaXMLファイルを読み出す部分(つまりは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のものが 使われるという点に注意が必要です。