XML
已经成为了我们开发过程中不可缺少的技术。我们可以用它来描述程序的配置,适配不同的数据格式,甚至作为
数据库
使用。
帮助处理 XML 的工具很多,它们让我们活得更轻松。 Jakarta Commons 下的 Digester 就是一个不错的工具。它提供了一种将 XML 与 Java 对象进行映射的方便方法。这么说可能让新手更迷惑,还是举个例子吧!
我们有这样一个 XML 文件:
帮助处理 XML 的工具很多,它们让我们活得更轻松。 Jakarta Commons 下的 Digester 就是一个不错的工具。它提供了一种将 XML 与 Java 对象进行映射的方便方法。这么说可能让新手更迷惑,还是举个例子吧!
我们有这样一个 XML 文件:
1.
2.
<!-- Memos_2004-01-16.xml -->
3.
<?xml version=
"1.0"
?>
4.
<memos>
5.
<memo>
6.
<title>About Jakatar commons Digester</title>
7.
<date>2004-01-16 02:05</date>
8.
<body>We are working on Digester 1.6-dev.Because it supported read
9.
attributes of element.We should pay attention to the releasing of
10.
Digester
for
its changing.</body>
11.
</memo>
12.
13.
<memo>
14.
<title>Ah ha! It's good night!</title>
15.
<date>2004-01-16 4:19</date>
16.
<body>I has enhanced the basic framework of my app with improved
17.
architecture and performance. It's time to sleep. Good night,
18.
boys.</body>
19.
</memo>
20.
</memos>
这是我的备忘录,我用
xml
作为
“
数据库
”
。现在我们想用
Java
程序来读
/
写这个
“
数据库
”
应该怎么做呢?啊!对了,
SAX
、
DOM……
,好了,忘了它们吧!我们有更
Easy
的办法!
我们先来创建一个 Memo 类,它用来保存一条 Memo 。它有三个属性用来保存标题、日期以及 Memo 的正文。我们提供了公共的 Setter 和 Getter ,并且我们重载了 toString() 方法以便查看运行结果
我们先来创建一个 Memo 类,它用来保存一条 Memo 。它有三个属性用来保存标题、日期以及 Memo 的正文。我们提供了公共的 Setter 和 Getter ,并且我们重载了 toString() 方法以便查看运行结果
1.
2.
/* Memo.java */
3.
package
kitta.memo;
4.
1.
public
class
Memo
2.
{
3.
/*-----/ Instance Field(s) /------------------------------------------------*/
4.
private
String _title;
5.
private
String _body;
6.
private
String _date;
7.
/*-----/ Constructor(s) /---------------------------------------------------*/
8.
public
Memo()
9.
{
10.
/* do nothing now */
11.
}
12.
13.
/*-----/ Getter(s) & Setter(s) /--------------------------------------------*/
14.
public
String getBody()
15.
{
16.
return
_body;
17.
}
18.
19.
public
void
setBody(String body)
20.
{
21.
_body = body;
22.
}
23.
24.
public
String getTitle()
25.
{
26.
return
_title;
27.
}
28.
29.
public
void
setTitle(String title)
30.
{
31.
_title = title;
32.
}
33.
34.
public
String getDate()
35.
{
36.
return
_date;
37.
}
38.
public
void
setDate(String date)
39.
{
40.
_date = date;
41.
}
42.
/*-----/ Overrided Method(s) /----------------------------------------------*/
43.
public
String toString()
44.
{
45.
StringBuffer buf =
new
StringBuffer();
46.
buf.append(
"/t"
).append(_title);
47.
buf.append(
"/tat/t"
).append(_date).append(
"/n/n"
);
48.
buf.append(
"/t"
).append(_body).append(
"/n"
);
49.
buf.append(
"-----------------------------------------------------------/n"
);
50.
return
buf.toString();
51.
}
52.
}
然后是
Memos
类,它实际上是一个
Memo
对象的集合,完全可以用一个
Collection
的子类去代替它,但是这里之所以还是使用它主要是为了概念上的清晰。它同样很简单,一个私有属性
_memos
用来保存所有
Memo
对象的实例,一个共有方法
addMemo()
用来添加
Memo
,
toString()
方法的目的同上。
1.
/* Memos.java */
2.
package
kitta.memo;
3.
4.
import
java.util.Collection;
5.
import
java.util.Iterator;
6.
import
java.util.Vector;
7.
8.
9.
public
class
Memos
10.
{
11.
/*-----/ Instance Fields /--------------------------------------------------*/
12.
private
Collection _memos=
new
Vector();
13.
/*-----/ Constructor(s) /---------------------------------------------------*/
14.
public
Memos()
15.
{
16.
/* do nothing */
17.
}
18.
/*-----/ Getter(s) & Setter(s) /--------------------------------------------*/
19.
public
void
addMemo(Memo memo)
20.
{
21.
_memos.add(memo);
22.
}
23.
/*-----/ Overrided Method(s) /----------------------------------------------*/
24.
public
String toString()
25.
{
26.
StringBuffer buf =
new
StringBuffer();
27.
buf.append(
"-----------------------------------------------------------/n"
);
28.
buf.append(
" Memo Application/n"
);
29.
buf.append(
" ("
).append(_memos.size()).append(
" memos total found.)/n"
);
30.
buf.append(
"-----------------------------------------------------------/n"
);
31.
32.
for
(Iterator itr = _memos.iterator();itr.hasNext();)
33.
{
34.
Memo m = (Memo) itr.next();
35.
buf.append(m.toString());
36.
}
37.
return
buf.toString();
38.
}
39.
}
1.
2.
package
kitta.memo;
3.
4.
import
java.io.IOException;
5.
import
java.io.InputStream;
6.
7.
import
org.apache.commons.digester.Digester;
8.
9.
public
class
MemoApp
10.
{
11.
/*-----/ Instance Field(s) /------------------------------------------------*/
12.
private
Memos _memos;
13.
/*-----/ Constructor(s) /---------------------------------------------------*/
14.
public
MemoApp()
15.
{
16.
/* do nothing */
17.
}
18.
/*-----/ Private Methods(s) /-----------------------------------------------*/
19.
/**
20.
* Initializes the instance of Digester.
21.
*/
22.
private
void
init(Digester dgstr)
23.
{
24.
/*
当遇到
memos
元素时创建一个
Memos
对象
*/
25.
dgstr.addObjectCreate(
"memos"
, Memos.
class
);
26.
/*
当遇到
memo
元素时创建一个
Memo
对象
*/
27.
dgstr.addObjectCreate(
"memos/memo"
, Memo.
class
);
28.
/*
当遇到
memos/memo/title
元素时,调用当前
Memo
对象的
setTitle
方法
*/
29.
dgstr.addBeanPropertySetter(
"memos/memo/title"
,
"title"
);
30.
/*
当遇到
memos/memo/body
元素时,调用当前
Memo
对象的
setBody */
31.
dgstr.addBeanPropertySetter(
"memos/memo/body"
,
"body"
);
32.
/*
当遇到
memos/memo/date
元素时,调用当前
Memo
对象的
setDate
方法
*/
33.
dgstr.addBeanPropertySetter(
"memos/memo/date"
,
"date"
);
34.
/*
调用当前的
Memos
对象的
addMemo
方法,参数为当前的
Memo
对象
*/
35.
dgstr.addSetNext(
"memos/memo"
,
"addMemo"
);
36.
37.
}
38.
/**
39.
* prints details of memos to standard out.
40.
*/
41.
private
void
print()
42.
{
43.
System.out.println(_memos);
44.
}
45.
/**
46.
* maps the xml data to java object
47.
*/
48.
private
void
load(InputStream in)
throws
Exception
49.
{
50.
Digester dgstr =
new
Digester();
- init(dgstr);
52.
try
53.
{
54.
_memos = (Memos) dgstr.parse(in);
55.
}
catch
(IOException e)
56.
{
57.
throw
new
Exception(
"Error occured When loading data"
,e);
58.
}
59.
}
60.
/*-----/ Main Method /------------------------------------------------------*/
61.
public
static
void
main(String[] args)
throws
Exception
62.
{
63.
MemoApp mapp =
new
MemoApp();
64.
/* load xml file from classpath */
65.
mapp.load(MemoApp.
class
.getResourceAsStream(
"/kitta/memo/memo.xml"
));
66.
mapp.print();
67.
}
68.
}
Digester
用
"elem/elem/elem"
的方式来匹配
xml
中的元素。这非常直观,实际上我们很早就开始使用类似的方式了。
Digester
将其称为
Pattern
。
Digester
中还有一个重要的概念就是
Rule
。我们在
init
方法中所做的就是将
Pattern
和
Rule
关联起来。当
Digester
发现与我们所注册的
Pattern
匹配的
xml
元素时,就会调用我们注册时指定
Rule
来处理这个元素。
环境
以上代码的测试环境为 Windows XP 、 JDK 1.4.2 03 、 Digester 1.5 Release 。
以上代码的测试环境为 Windows XP 、 JDK 1.4.2 03 、 Digester 1.5 Release 。
相关资源
Degister 官方资源
Web site: http://jakarta.apache.org/commons/digester/index.html
CVS connection: scm:cvs:pserver:anoncvs@cvs.apache.org:/home/cvspublic:jakarta-commons/digester/
CVS Web View: http://cvs.apache.org/viewcvs/jakarta-commons/digester/
一些其它地方的文章:
http://www-106.ibm.com/developerworks/java/library/j-lucene/
http://www.javaworld.com/javaworld/jw-10-2002/jw-1025-opensourceprofile.html
http://www.onjava.com/pub/a/onjava/2002/10/23/digester.html
Degister 官方资源
Web site: http://jakarta.apache.org/commons/digester/index.html
CVS connection: scm:cvs:pserver:anoncvs@cvs.apache.org:/home/cvspublic:jakarta-commons/digester/
CVS Web View: http://cvs.apache.org/viewcvs/jakarta-commons/digester/
一些其它地方的文章:
http://www-106.ibm.com/developerworks/java/library/j-lucene/
http://www.javaworld.com/javaworld/jw-10-2002/jw-1025-opensourceprofile.html
http://www.onjava.com/pub/a/onjava/2002/10/23/digester.html
最后
好啦!就这么简单!因为这只是一些基本的应用,它可以帮助你了解 Digester ,毕竟这只是一个 Getting Start 吗!要更好的应用,就要更深入的研究。
好啦!就这么简单!因为这只是一些基本的应用,它可以帮助你了解 Digester ,毕竟这只是一个 Getting Start 吗!要更好的应用,就要更深入的研究。