JavaによるDOM Level 3 Load and Saveの利用方法

はじめに

ここではJavaでDOM Level 3 Load and Saveを利用する方法を説明します。Javaのバージョンは1.5(J2SE 5.0)以降である必要があります。また、XMLプロセッサとしてXercesを利用します。以下のページからダウンロードしてください。

以下のサンプルコードはJDK 5.0 Update 8、Xerces2 Java 2.8.0でコンパイル&実行可能であることを確認しています。

Note: Java 1.6(Java SE 6)では、別途Xercesを用意する必要はありません。

概要

DOM 3 Load and Saveでは、LSParserでXMLの読み込みを行い、LSSerializerでXMLの書き込みを行います。LSParserやLSSerializerなど、必要なオブジェクトはDOMImplementationLSを用いて取得することができます。

DOMImplementationLSの取得

Java 1.5ではorg.w3c.dom.bootstrapパッケージが追加され、DOMImplementationRegistryクラスを用いてDOMImplementationのインスタンスを取得できるようになりました。DOMImplementationRegistryで取得できるインスタンスはシステムプロパティ"DOMImplementationSourceList"によって決まります。つまり、"DOMImplementationSourceList"プロパティを変更するだけで、ソースコードを書き換えなくてもDOMの実装を変更できます。

xercesImpl.jarには、このプロパティを設定するためのファイルが含まれています。そのため、xercesImpl.jarをクラスパスに含めるだけでXercesを利用することができます。

DOMImplementationRegistryのインスタンスはnewInstance()メソッドを用いて取得できます。また、DOMImplementationLSのインスタンスはDOMImplementationRegistryのgetDOMImplementation()メソッドで取得します。

/* DOMImplementationRegistryからDOMImplementationLSの取得 */
DOMImplementationRegistry registry = 
        DOMImplementationRegistry.newInstance();
DOMImplementationLS domImpLS = 
        (DOMImplementationLS)registry.getDOMImplementation("LS 3.0");

DOMツリーの読み込み - LSParserとLSInput

XML文書を読み込むときは、LSInputで読み込み元を指定し、それをLSParserで読み込みます。LSInputとLSParserのインスタンスはDOMImplementationLSを用いて生成します。

/* ファイル(sample.xml)から読み込む場合の例 */
// LSInputの生成
FileInputStream fin = new FileInputStream("./sample.xml");
LSInput input = domImpLS.createLSInput();
input.setByteStream(fin);

// LSParserの生成とXML文書の読み込み
LSParser parser = domImpLS.createLSParser(
        DOMImplementationLS.MODE_SYNCHRONOUS, null);
Document doc = parser.parse(input);

同期モードと非同期モードについて

DOMImplementationLSのcreateLSParser()メソッドの第1引数にはMODE_SYNCHRONOUS(同期モード)またはMODE_ASYNCHRONOUS(非同期モード)を指定します。

同期モードでは、LSParserのparse()メソッドやparseURI()メソッドによりXML文書が解析され、これらのメソッドがDocumentオブジェクトを返します。この時、解析処理はメソッドの呼び出し元と同一のスレッドで行われます。

一方、非同期モードでは、LSParserのparse()メソッドやparseURI()メソッドを呼ぶと別スレッドでXML文書が解析されます。そのため、これらのメソッドはnullを返し、解析結果はLSLoadEventのgetNewDocument()メソッドで取得します。非同期LSParserオブジェクトはEventTargetインタフェースを実装していて、addEventListener()メソッドでLSLoadEventのEventListenerを登録できます。

Note: Java 1.6のデフォルトの実装では、非同期モードはサポートされていないようです。

DOMツリーの書き込み - LSSerializerとLSOutput

DOMツリーを保存するときは、LSOutputで書き込み先を指定し、LSSerializerでそれに書き込みます。LSOutputとLSSerializerのインスタンスはDOMImplementationLSを用いて生成します。

/* 標準出力に書き出す場合の例 */
// LSOutputの生成
LSOutput output = domImpLS.createLSOutput();
output.setByteStream(System.out);
output.setEncoding("Shift_JIS"); // 文字コードの指定

// LSSerializerの生成とXML文書の出力
LSSerializer serializer = domImpLS.createLSSerializer();
serializer.write(doc, output);

サンプルコード

上記のコードをまとめると以下のようになります。

/* sample.xmlを読み込んで標準出力に書き出すプログラム */
import java.io.FileInputStream;
import org.w3c.dom.Document;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSParser;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSSerializer;
import org.w3c.dom.ls.LSOutput;

public class Sample {
    public static void main(String[] args) {
        try {
            // DOMImplementationLSのインスタンスを取得
            DOMImplementationRegistry registry = 
                    DOMImplementationRegistry.newInstance();
            DOMImplementationLS domImpLS = 
                    (DOMImplementationLS)registry.getDOMImplementation("LS 3.0");
            
            // LSInputの生成
            FileInputStream fin = new FileInputStream("./sample.xml");
            LSInput input = domImpLS.createLSInput();
            input.setByteStream(fin);
            
            // LSParserの生成とXML文書の読み込み
            LSParser parser = domImpLS.createLSParser(
                    DOMImplementationLS.MODE_SYNCHRONOUS, null);
            Document doc = parser.parse(input);
            
            // LSOutputの生成
            LSOutput output = domImpLS.createLSOutput();
            output.setByteStream(System.out);
            output.setEncoding("Shift_JIS");
            
            // LSSerializerの生成とXML文書の出力
            LSSerializer serializer = domImpLS.createLSSerializer();
            serializer.write(doc, output);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

実行するときはxercesImpl.jarをクラスパスに含めます。例えば以下のように。

java -cp .;xercesImpl.jar Sample

Note: Java 1.6(Java SE 6)では、xercesImpl.jarをクラスパスに設定しなくても作動します。

参考文献

J2SE 5.0 API 仕様

W3Cの仕様