XML to Javaのデータバインディングツール。元はStrutsの設定ファイルの読み込みで使っていたらしい。「読み込み」だけしかできないが、使い方が簡単。
http://jakarta.apache.org/commons/digester/
推奨環境
- Logging 1.1.x
- BeanUtils 1.7
互換性
- Logging 1.1.x
- BeanUtils 1.x
- Collections 2.x
今回は
- Digester 1.8
- Bean Utils 1.7
- Logging 1.1
で使ってみた。
使い方
用意しなければならないのが、「パターンとルールの定義」。これはJavaに記述もできるし、XMLファイルに記述することもできる。
あとは、DigesterがXMLを読み込むときに使われるオブジェクトスタックを使ったオブジェクトの管理方法を理解しておくといい。
ルールをXMLで利用する
こちらのほうが便利なのでこちらを使ってDigesterを動かす。
ルールファイル
まずは、読み込むファイルを決める。複雑なXML構造にするよりも、単純な構造のほうがいい。今回はユーザを読み込むという前提。
<items>
<user>
<name>藤原</name>
<age>20</age>
</user>
<user>
<name>ああああ</name>
<age>20</age>
</user>
</items>
このように、
- user
- userの属性
と、だんだん深くなる構造がDigesterを使う上でとてもうれしい。なぜならば、Digesterはスタック構造を使っているので、深くなったり、浅くなったりすると、読み込みルールがとても難しくなる。
ルールファイルは以下のように記述する。DTDはJarファイルの中にある。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE digester-rules PUBLIC
"-//Jakarta Apache //DTD digester-rules XML V1.0//EN"
"digester-rules.dtd">
<digester-rules>
<!-- items要素が現れたらArrayListを作ります -->
<pattern value="items">
<object-create-rule classname="java.util.ArrayList" />
</pattern>
<!-- item/userが現れたらUserVOを作ります -->
<!-- UserVOを作ったら一つ上のクラス(ここではArrayList)の
addメソッドを呼びます。引数はさっき作ったUserVOです -->
<pattern value="items/user">
<object-create-rule classname="com.daipresents.digester18.UserVO" />
<set-next-rule methodname="add" />
</pattern>
<!-- item/user/nameが現れたらUserVO.setNameメソッドを呼びます
引数には要素の値を使います -->
<pattern value="items/user/name">
<bean-property-setter-rule propertyname="name"/>
</pattern>
<!-- item/user/ageが現れたらUserVO.setAgeメソッドを呼びます
引数には要素の値を使います -->
<pattern value="items/user/age">
<bean-property-setter-rule propertyname="age"/>
</pattern>
</digester-rules>
スタック構造
Digesterはスタックを用いてオブジェクトを生成する。上記ルールの場合は、
- ArrayList(結果戻り値はこれ)
- UserVO
- UserVO
- ・・・
と作られていく(プッシュ)。スタックなので、一番下にArrayList、その上にUserVO、UserVO・・・となっていて、取り出す場合は、一番上のオブジェクトしか取り出せない(ポップ)。
つまり、Digesterでたくさんのオブジェクトを作ることはできるけど、結局返すオブジェクトは1つになってしまう。Digesterではルートオブジェクトの中に、ガシガシとオブジェクトを設定していく感じになる。
Digesterのルールは
- ルートオブジェクト(一番初めに作られたオブジェクト)
- トップオブジェクト(一番最近作られたオブジェクト、子オブジェクトとも呼ぶ)
- (トップ – 1)オブジェクト(一つ前に作成されたオブジェクトの、一番新しいUserVOの「親オブジェクト」と呼ぶ)
の3つしか操作しかできない。
Digesterの実行クラス
実行は簡単で
- ルールを読み込む
- 解析(パース)する
だけで、ルールに記述した形でクラスを取得できる。
今回は複数のUser要素を読み込むので、「UserVOを持ったList」をDigesterに作ってもらう。
Digester digester = null;
try {
digester =
DigesterLoader.createDigester(
new File(
"D:/daipresents/project/Digester1.8/conf/digester-rules02.xml").toURI().toURL());
List<UserVO> list =
(List<UserVO>) digester.parse(
new File("D:/daipresents/project/Digester1.8/conf/input02.xml").toURI().toURL());
trace(list);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
UserVOはゲッター&セッターをもったバリューオブジェクト。
public class UserVO {
private String name;
private String age;
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
実行結果は以下のようになる。traceメソッドを作ってVOの中身を表示してみた。
***UserVO***
name = 藤原
age = 20
***UserVO***
name = ああああ
age = 20