Test.xml
1
<?xml version="1.0" encoding="UTF-8"?>
2
3
<foo name="The Parent">
4
5
<bar id="123" title="The First Child" />
6
7
<bar id="456" title="The Second Child" />
8
9
</foo>
10
Foo.java
1
package foo;
2
3
import java.util.*;
4
5
publicclass Foo
{
6
7
private List list = new ArrayList();
8
9
publicvoid addBar(Bar bar)
{
10
11
list.add(bar);
12
13
}
14
15
public List getBar()
{
16
17
returnlist;
18
19
}
20
21
}
22
23
Bar.java
1
package foo;
2
3
publicclass Bar
{
4
5
private String id;
6
7
private String title;
8
9
public String getId()
{
10
11
returnid;
12
13
}
14
15
publicvoid setId(String id)
{
16
17
this.id = id;
18
19
}
20
21
public String getTitle()
{
22
23
returntitle;
24
25
}
26
27
publicvoid setTitle(String title)
{
28
29
this.title = title;
30
31
}
32
33
}
34
35
Test.java
1
package simple;
2
3
import org.apache.commons.logging.Log;
4
5
import org.apache.commons.logging.LogFactory;
6
7
import org.apache.commons.digester.Digester;
8
9
import org.xml.sax.SAXException;
10
11
import java.io.IOException;
12
13
import foo.Foo;
14
15
publicclass Test
{
16
17
private Log log = LogFactory.getLog(getClass());
18
19
/** *//**
20
21
*@paramargs
22
23
*/
24
25
publicstaticvoid main(String[] args)
{
26
27
// TODO Auto-generated method stub
28
29
Digester digester = new Digester();
30
31
//不进行XML与相应的DTD的合法性验证
32
33
digester.setValidating(false);
34
35
//当遇到<foo>时创建一个mypackage.Foo对象,并将其放在栈顶
36
37
digester.addObjectCreate("foo", "foo.Foo");
38
39
//根据<foo>元素的属性(attribute),对刚创建的Foo对象的属性(property)进行设置
40
41
digester.addSetProperties("foo");
42
43
//当遇到<foo>的子元素<bar>时创建一个mypackage.Bar对象,并将其放在栈顶。
44
45
digester.addObjectCreate("foo/bar", "foo.Bar");
46
47
48
49
//根据<bar>元素的属性(attribute),对刚创建的Bar对象的属性(property)进行设置
50
51
digester.addSetProperties("foo/bar");
52
53
//当再次遇到<foo>的子元素<bar>时创建一个mypackage.Bar对象,并将其放在栈顶,同时调用第二栈顶元素(Foo对象)的addBar方法。
54
55
digester.addSetNext("foo/bar", "addBar", "foo.Bar");
56
57
try
{
58
59
//分析结束后,返回根元素。
60
61
Foo foo = (Foo) digester.parse(Test.class
62
63
.getResourceAsStream("/test.xml"));
64
65
System.out.println("Bar size= " + foo.getBar().size());
66
67
} catch (IOException e)
{
68
69
// TODO Auto-generated catch block
70
71
e.printStackTrace();
72
73
} catch (SAXException e)
{
74
75
// TODO Auto-generated catch block
76
77
e.printStackTrace();
78
79
}
80
81
}
82
83
}
84
85
1 digester.setValidating(false);
2 digester.push(this);
3 digester.addObjectCreate("foo/bar", "foo.Bar");
说明:
digester.push(this); //不是必须
1,2两个同时使用时,必须先验证然后push。
3 “foo/bar”,若非业务需要,不必为foo元素单独创建一个Java Bean。
基本情况
熟悉用SAX来处理XML文档的程序员,会发现Digester隐藏了遍历XML元素这些细节,而是提供了更高一层的、更友好的SAX事件接口,从而让程序员的精力放在对数据的处理过程中。
使用Digester,须按照以下步骤:
1. 创建一个org.apache.commons.digester.Digester实例。一个解析请求完成后,这个Digester可以被后面复用。但也不要试图在不同的线程中从共享一个Digester实例。
2. 根据需要设置一些配置属性(configuration properties),以控制下一步的解析操作。
3. 将一个或几个初始对象(initial object)压入Digester对象栈,本步骤不是必须的。
4. 注册所有的元素匹配模板(elemet matching pattern)。当一个模板被从输入文档中识别出来以后,与其相联系的处理规则(processing rules)被激活。对一个特定的模板,可以定义任意多的规则,当识别出该模板后,这些规则依序依次执行。
5. 调用digester.parse()方法,一个XML文档的引用(用多种方式供选择)要传给这个方法。同时返回整个堆栈(并移除digester中的整个堆栈)。注意,需要捕捉并处理IOException或SAXEception或处理过程中抛出的异常。
对象栈
对digester技术最普通的应用,是用来动态创建一个由Java对象构成的树结构,各对象的属性以及对象间的关系,基于XML文档的内容来设置(XML文档就是一棵树)。为实现这种应用,Digester提供了一个对象栈,以供在相关的模板识别后被激活的处理规则操作。此栈的基本操作包括:
1. clear(),清空栈的内容
2. peek(),返回对栈顶对象的引用
3. pop(),将栈顶对象弹出并返回
4. push(),将一个新的对象压入栈顶
用栈的原因,就是当识别出一个XML元素的“开始”时,将相关对象生成并压入栈顶,这个对象在处理该元素的子元素的过程中一直在栈中,当所有子元素都处理完后,解析器遇到这个元素的“结束”时,则弹出此对象,并进行相关的处理。
如何描述对象间的关系呢?将栈顶的对象做为一个参数,传递给第二栈顶(即先于栈顶对象入栈的那个对象,在栈顶对象的下面)的一个方法,就可以简单地建立起一种“父子关系”,从而可以简单地建立起1:1的关系(第二栈顶对象与栈顶对象之间)和1:N的关系(第二栈顶对象不动,N次压栈顶弹栈顶对象).
如果取得生成的第一个对象呢?可以让parse()方法返回,或者在调用parse()方法前,先行压入一个对象,在parse()方法结束后弹出这个对象,则其子对象即为我们想要的第一个对象。
参考资料
Digester学习笔记
http://macrochen.blogdriver.com/macrochen/348236.html