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