Commons

作成 2002/10/29

Digester

Digesterって?

DigesterはXML→Javaバインディングツールです。 XMLをパースして、内容をJavaオブジェクトに保存するための 簡単なAPIを提供しています。 設定ファイルを読み込む場合などに重宝します。 XML→Javaバインディングなので、Java→XMLということはできません。 バインディングツールとしては、他にJAXBなどもありますが、 使えるようになるのは来年以降でしょう。

使ってみる

実行には、commons-digesterのjarが必要です。 Jakartaからダウンロードします。 ここではバージョン1.3を使いました。

また、他に依存している以下のjarが必要です。

以下の簡単なXMLを読み込んでみます。

hoge.xml

<?xml version="1.0" encoding="Shift_JIS"?>
<hoge>
  <foo name="foo1">
    <message>foofoo</message>
    <bar name="bar1"
      age="10"/>
    <bar name="bar2"
      age="11"/>
  </foo>
</hoge>

値を格納するbeanを作ります。

Hoge.java

public class Hoge {

  private Foo foo;

  public String toString(){
    return super.toString()
      + ",foo=" + foo
      ;
  }

  public Foo getFoo() {
    return foo;
  }

  public void setFoo(Foo foo) {
    this.foo = foo;
  }
}

ただのbeanです。子要素にFooを持ちます。

Foo.java

import java.util.*;

public class Foo {

  private String message;

  private List bars = new ArrayList();

  public String toString(){
    return super.toString()
      + ",message=" + message
      + ",bars=" + bars
      ;
  }

  public String getMessage() {
    return message;
  }

  public void setMessage(String message) {
    this.message = message;
  }

  public void addChild(Bar bar){
    bars.add(bar);
  }

  public List getBars(){
    return bars;
  }
}

子要素に複数のBarを持ちたいので、 フィールドをリストにし、addChild()メソッドを定義しました。 他に、messageも持ちます。

Bar.java

public class Bar {

  private String name;
  private int age;

  public String toString(){
    return super.toString()
      + ",name=" + name
      + ",age=" + age
      ;
  }

  public int getAge() {
    return age;
  }

  public String getName() {
    return name;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public void setName(String name) {
    this.name = name;
  }
}

これもただのbeanです。

toString()は値が入っていることを確認するためで、 必須ではありません。

でもって、実際にDigesterを使って、XMLをパースし、 読み込んでみます。

import java.io.*;
import javax.xml.parsers.*;
import org.apache.commons.digester.*;

public class SimpleDigester {

  public static void main(String[] args) throws Exception{

    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser parser = factory.newSAXParser();
    Digester digester = new Digester(parser);

    //hogeがきたらHogeを作る
    digester.addObjectCreate("hoge", Hoge.class);

    //hoge/fooがきたらFooを作る
    //hoge.setFoo(foo)する
    //foo.setXXX(*)する
    digester.addObjectCreate("hoge/foo", Foo.class);
    digester.addSetNext("hoge/foo", "setFoo");
    digester.addSetProperties("hoge/foo");

    //foge/foo/messageがきたら
    //foo.setMessage(messageテキスト)
    digester.addBeanPropertySetter("hoge/foo/message");

    //hoge/foo/barがきたらBarを作る
    //foo.addChild(bar)する
    //bar.setXXX(*)する
    digester.addObjectCreate("hoge/foo/bar", Bar.class);
    digester.addSetNext("hoge/foo/bar", "addChild");
    digester.addSetProperties("hoge/foo/bar");

    //パースする
    InputStream in = new FileInputStream("src/digester/hoge.xml");
    Hoge hoge = (Hoge)digester.parse(in);
    
    System.out.println(hoge);

  }
}

addObjectCreate()で、インスタンスをつくり、 addSetNext()で、一つ上(のスタック)のオブジェクトのメソッドを呼び、 addSetProperties()で全ての属性を一括セットできます。

もっと細かくやるには、自分でRuleクラスを作るみたいです。

やることは簡単ですが、調べるのに苦労しました。サンプルが沢山あればいいのに。

参考


TOP