Java で XML 文書を読み込んで DOM ツリーを構築するサンプル

XML 文書をツリー形式で扱うためのモデルとして DOM があり、W3C がその仕様を公開しています。 例えば DOM 3 Core Specification などです。

しかし、XML 文書を読み込んで DOM ツリーを構築したり、逆に DOM ツリーから XML 文書を出力したりするという部分については実装依存だと (今まで) 思っていました。 が、実はその部分 (内部処理ではなく API に関して) もちゃんと仕様がありました。

そしてちゃんと Java でも実装されているというからびっくりしました。 「Java DOM XML」 などのキーワードで検索して XML 文書をパースして DOM 木を取得する方法を調べると、検索の上位は javax.xml.parsers.DocumentBuilder クラス を使用する方法で占められているので今まで全く気づきませんでした。

せっかくなので javax.xml.parsers.DocumentBuilder クラス を使用して XML 文書をパースし javax.xml.transform.Transformer クラス を使用してシリアライズするサンプルと、W3C Load and Save の API を使ってパースおよびシリアライズするサンプルを置いておきます。

DocumentBuilder クラスおよび Transformer クラスを使用

XML 文書のパースに javax.xml.parsers.DocumentBuilder クラス を使用し、DOM ツリーを文字列に変換して出力するために javax.xml.transform.Transformer クラス を使用する方法です。

package info.vividcode;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

public class DOMTest1 {
public static void main( String[] args ) {
try {

// ===== XML 文書のパース =====
// DocumentBuilder クラスのインスタンスを取得
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
// パース
Document doc = builder.parse( new File("file.xml") );

// ===== DOM ツリーのシリアライズ =====
// Transformer クラスのインスタンスを取得
TransformerFactory tff = TransformerFactory.newInstance();
Transformer transformer = tff.newTransformer();
// シリアライズする DOM オブジェクト
DOMSource src = new DOMSource();
src.setNode( doc );
// シリアライズした結果を出力する先
StreamResult output = new StreamResult();
output.setOutputStream( System.out );
// シリアライズ
transformer.transform( src, output );

} catch ( Exception e ) {
e.printStackTrace();
}
}
}

DOM Load and Save の API を使用する方法

DOM Load and Save で規定されているインターフェイスを使用して XML 文書のパース、および DOM ツリーのシリアライズを行うサンプルです。

package info.vividcode;

import java.io.FileInputStream;

import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSParser;
import org.w3c.dom.ls.LSSerializer;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;

public class DOMTest2 {
public static void main( String[] args ) {
try {

// ===== Load and Save に関する実装取得 =====
// DOMImplementationLS のインスタンスを取得
DOMImplementationRegistry dir = DOMImplementationRegistry.newInstance();
DOMImplementation imp = dir.getDOMImplementation("+LS 3.0");
// 本来はここで imp が null でないかチェックすべき (該当する DOM 実装が無ければ imp は null)
DOMImplementationLS impLS = (DOMImplementationLS) imp.getFeature("+LS", "3.0");

// ===== XML 文書のパース =====
// LSInput クラスのインスタンスを取得し, 読み込み元設定
LSInput input = impLS.createLSInput();
input.setByteStream( new FileInputStream("file.xml") );
// LSParser クラスのインスタンス取得
LSParser parser = impLS.createLSParser(
DOMImplementationLS.MODE_SYNCHRONOUS, null );
// パース
Document doc = parser.parse(input);

// ===== DOM ツリーのシリアライズ =====
// LSOutput クラスのインスタンスを取得し, 出力先設定
LSOutput output = impLS.createLSOutput();
output.setByteStream( System.out );
output.setEncoding( "UTF-8" );
// LSSerializer クラスのインスタンス取得
LSSerializer serializer = impLS.createLSSerializer();
// シリアライズ
serializer.write( doc, output );

} catch( Exception e ) {
e.printStackTrace();
}
}
}

変更

      DOMImplementationLS impLS = 
(DOMImplementationLS) dir.getDOMImplementation("LS 3.0");
となっていたところを
      DOMImplementation   imp   = dir.getDOMImplementation("Core 3.0");
DOMImplementationLS impLS = (DOMImplementationLS) imp.getFeature("LS", "3.0");
と変更しました。 こちらの方が W3C DOM に従った形になっているはずです。 [2009.10.12 朝]

さらに

      DOMImplementation   imp   = dir.getDOMImplementation("+LS 3.0");
// 本来はここで imp が null でないかチェックすべき (該当する DOM 実装が無ければ imp は null)
DOMImplementationLS impLS = (DOMImplementationLS) imp.getFeature("+LS", "3.0");
と変更しました。 dir.getDOMImplementation("+LS 3.0") で、Load and Save 機能を実装している、または協調可能な DOM 実装を取得し、imp.getFeature("+LS", "3.0") で Load and Save 機能を実装しているオブジェクトを取得しています。 [2009.10.12 夜]