在windows下开发程序,用M$提供的接口处理.ini文件或管理注册表的键值是非常方便的。在java平台上开发程序,则习惯于以xml格式的文件来存放系统的配置信息,对这种文件的解析和处理,可以用sax或 dom。有没有更简便的方法呢?有,就是用digester模块。
Digester是Jakarta 子项目Commons下的一个模块,支持基于规则的对任意XML文档的处理。它最初是Structs项目的一部分,后因其通用性而划归Commons.
password: anoncvs
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout jakarta-commons/digester
cd jakarta-commons/digester
ant dist
Digester的运行依赖下列包:
public class Foo {
public void addBar(Bar bar);
public Bar findBar(int id);
public Iterator getBars();
public String getName();
public void setName(String name);
}
public mypackage;
public class Bar {
public int getId();
public void setId(int id);
public String getTitle();
public void setTitle(String title);
}
用下面的xml文件进行配置
用下面几行代码即可完成配置文件解析工作:
Digest解析代码
注释
Digester digester = new Digester();
digester.setValidating(false);
不进行XML与相应的DTD的合法性验证
digester.addObjectCreate("foo", "mypackage.Foo");
当遇到时创建一个mypackage.Foo对象,并将其放在栈顶
digester.addSetProperties("foo");
根据元素的属性(attribute),对刚创建的Foo对象的属性(property)进行设置
digester.addObjectCreate("foo/bar", "mypackage.Bar");
当遇到的子元素时创建一个mypackage.Bar对象,并将其放在栈顶。
digester.addSetProperties("foo/bar");
根据元素的属性(attribute),对刚创建的Bar对象的属性(property)进行设置
digester.addSetNext("foo/bar", "addBar", "mypackage.Bar");
当再次遇到的子元素时创建一个mypackage.Bar对象,并将其放在栈顶,同时调用第二栈顶元素(Foo对象)的addBar方法。
Foo foo = (Foo) digester.parse();
分析结束后,返回根元素。
使用Digester,须按照以下步骤:
具体说来,元素和其子元素间,用”/”相隔,如果一些元素前没有”/”则其必为根元素。如例:
-- 匹配模板 "a/b"
-- 匹配模板 "a/b/c"
-- 匹配模板 "a/b/c"
-- 匹配模板 "a/b"
-- 匹配模板 "a/b/c"
-- 匹配模板 "a/b/c"
-- 匹配模板 "a/b/c"
字符”*”表示任意级别,如”*/a”表示任意级别的都可匹配(不包括根元素级的).熟悉XLST的朋友,对这种思路一定不陌生。
从上面的描述,可知某个元素同时满足多个匹配模板是非常可能的,在这种情况下,与各个模板相关联的处理规则(processing rule)的执行顺序如下:对begin或body方法,按照各个rule的注册顺序的先后,对end方法则是注册顺序的反序。
从形式上讲,一个处理规则是一个java类,它扩展了org.apache.commons.digester.Rule类。每个处理规则,实现下列的一个或几个事件处理方法(event method),当相应的模板匹配成功以后,在已定义的某个时刻,这些事件方法会被触发。
在设置digester时,通过调用addRule()方法,来注册一个特定的元素匹配模板以及相应的一个Rule类的实例。如上所述,Rule类中的事件处理方法,会在适当的时间被调用。这个机制,允许动态地生成Rule的实现。
另外,digester也提供了一些处理常见情况的处理规则类。
对这些标准的规则类,可以创建它们的实例,并调用digester.addRule来注册它们。由于经常使用它们,所以digester定义了一些简便的方法来注册它们。如:
digester.addRule("a/b/c", rule);