ファイヤープロジェクト
JavaでDOM
2003-07-20T15:13+09:00   matsu
JavaでDOMクラスライブラリを使用してプログラミングしてみる.
XMLパーサとして,DOMとSAXがある.これらは,XML文書をプログラムで扱う際の方式である.それぞれに対応したXMLパーサ(ライブラリ)が多くの言語で提供されている.DOMとSAXはどう違うのかは,本ページの「DOMとは」とJavaでSAXのページの「SAXとは」を参照.
DOMはData Object Modelの略である.JavaではSunがJAXP(Java API for XML Programing)というパッケージにDOMに対応したXMLパーサが入っている(このパッケージには,SAXに対応したXMLパーサも入っている).
DOMでは,XML文書を一気に読み込んで,要素のツリーを構築する.このツリーをランダムに行き来したり,削除したりすることができる.その代わり,要素のツリーを構築するために大きなXML文書を読み込むにはそれなりのメモリを必要とする.イメージとしてはDOMはXMLを大局的にとらえるのに向き,SAXは局所的にとらえるのに向く,と思う.
DOMのクラスライブラリを使うために.
apt-get install libcrimson-java libcrimson-java-doc
export CLASSPATH=/usr/share/java/xerces.jar
これでorg.apache.crimsonをimportできる.このパッケージやSAXのページで述べるパッケージのクラスのようにXML文書を扱うことのできるモジュールをXMLパーサと呼ぶ.apt-cache showによると,libcrimson-javaはJAXPをサポートしているらしい.
DOMでXML文書を読み込むと,ツリーが出来上がる.ツリーのノードとなるのは,タグやテキストなどである.DOMを使用すると,これらのノードを取得したり,子ノードに移動したりできる.もちろん要素の名前やノードの種類やノードの値などを取得できる.
DOMを使用したサンプルプログラムを以下に示す.
import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.apache.crimson.tree.*;

class DomSample{
    protected Document doc;
    protected int tab;

    public DomSample(String filename){
	try{
	    DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
	    DocumentBuilder db=dbf.newDocumentBuilder();
	    /* XML文書を読み込む.*/
	    doc=db.parse(new FileInputStream(filename));
	}catch(Exception e){
	    e.printStackTrace();
	}
	tab=0;
    }

    public void getNodeInfo(Node node){
	tabbing();
	/* ノードの種類を出力 */
	System.out.println("Node type= "+node.getNodeType());
	tabbing();
	/* ノード名を出力 */
	System.out.println("Node name= "+node.getNodeName());
	tabbing();
	/* ノードの値を出力 */
       	System.out.println("Node value= "+node.getNodeValue());
    }

    /* 全ノードを探索 */
    public void walkThrough(){
	Node root=doc.getDocumentElement();
	recursiveWalk(root);
    }

    private void recursiveWalk(Node node){
/*
これは,XML文書のインデントなどの空白のノードを読み飛ばすための処理.
Node.TEXT_NODE ノードがテキストで,ノードの値の空白を除いた文字列の長さが0の場合は読み飛ばす.
*/
	   
	if(node.getNodeType()==Node.TEXT_NODE && node.getNodeValue().trim().length()==0){
	    return;
	}
	getNodeInfo(node);
	tab++;
	/* node.getFirstChild : nodeの最初の子を得る */
	/* child.getNextSibling : childの兄弟ノードを得る */
	for(Node child=node.getFirstChild();child!=null;child=child.getNextSibling()){
	    recursiveWalk(child);
	}
	tab--;
    }

    protected void tabbing(){
	for(int i=0;i<tab;i++){
	    System.out.print("\t");
	}
    }

    public static void main(String args[]){
	DomSample ds=new DomSample("sample.xml");
	ds.walkThrough();
    }
}
このプログラムに以下のXML文書sample.xmlを読み込ませる.
<?xml version="1.0" encoding="Shift_JIS" ?>
<drinks>
    <drink type="soft">
        <name>Apple</name>
        <taste>Good</taste>
    </drink>

    <drink type="alcohol">
        <name>Beer</name>
	<taste>Bitter</taste>
    </drink>

    <drink type="alcohol">
        <name>Whiskey</name>
    </drink>
</drinks>
java DomSampleの実行結果を以下に示す.
Node type= 1
Node name= drinks
Node value= null
        Node type= 1
        Node name= drink
        Node value= null
                Node type= 1
                Node name= name
                Node value= null
                        Node type= 3
                        Node name= #text
                        Node value= Apple
                Node type= 1
                Node name= taste
                Node value= null
                        Node type= 3
                        Node name= #text
                        Node value= Good
        Node type= 1
        Node name= drink
        Node value= null
                Node type= 1
                Node name= name
                Node value= null
                        Node type= 3
                        Node name= #text
                        Node value= Beer
                Node type= 1
                Node name= taste
                Node value= null
                        Node type= 3
                        Node name= #text
                        Node value= Bitter
        Node type= 1
        Node name= drink
        Node value= null
                Node type= 1
                Node name= name
                Node value= null
                        Node type= 3
                        Node name= #text
                        Node value= Whiskey
うまく全ノード探索できた.
ここで述べたのはまだDOMのほんの入口に過ぎない.DOMでは要素,属性やテキストを読み込み,追加,削除,ツリーをXML文書として書き出すなどができるが,それらは以降に回す.
matsu(C)
Since 2002
Mail to matsu