最近在做一个小项目,需要读取数据字典XML中的内容取出相应的配置信息,在前台用Extjs生成一个查询框架,刚开始我是自己利用dom的开源lib以SAX的方式读数据字典,生成相应的java对象,但总感觉自己写的读取方法不是很完美,所以想在网上找找更好的解决办法。百度一下,看到了 Commons-Digester这个开源的jar文件,Digester本来仅仅是Jakarta Struts中的一个工具,用于处理struts-config.xml配置文件,后来就独立出来用于解析XML文件。
Digester由”事件”驱动,通过调用预定义的规则操作对象栈,将XML文件转换为Java对象。工作原理如下:
Digester底层采用SAX解析XML文件,所以很自然的,对象转换由”事件”驱动,即在识别出特定XML元素时(实际被细分为begin、 body、end、finish四个时点),将执行特定的动作,比如创建特定的Java对象,或调用特定对象的方法等。此处的XML元素根据匹配模式 (matching pattern)识别,而相关操作由规则(rule)定义。在转换过程中,Digester维持了一个对象栈,可以看作对象转换的工作台,用来存放转换中生成的、或是为转换临时创建的Java对象。对输入XML文件作了一趟完整的扫描后,对象栈的栈顶元素即为目标对象。由于Digester屏蔽了SAX解析的细节,使用者仅需关注转换操作本身,大大简化了转换操作。
使用Digester,基本步骤如下:
1.创建Digester对象实例。
2.设置该Digester对象的配置属性(可选)。
3.将需要的初始对象 push到该Digester对象的对象栈上(可选)。
4.需要注册所有的XML元素匹配模式与处理规则之间的映射关系。
5.用 digester.parse()解析的XML文档对象,得到目标对象。
在了解了Digester的实现原理和解析方式,就寻找网上现成的例子,自己在电脑上实现了一遍,由于网上的例子大多都不详细,所以在测试的过程中不断出现一些异常,但又不知道问题出自哪里、如何解决 
最后终于找到了一个比较详细的实例,呵呵
以下是一个测试方法,其它的代码没有贴出,如有需要可以告诉我:
package com.javachen.xml.digester;
import java.io.File;
import java.io.IOException;
import org.junit.Test;
import org.xml.sax.SAXException;
import org.apache.commons.digester.Digester;
import static org.junit.Assert.*;
public class DigesterTest {
/**
* 属性方式
*/
@Test
public void testOne() {
Digester digester = new Digester();
// 设置不进行合法性验证
digester.setValidating(false);
// 当遇到<teacher>时创建一个Teacher对象,放入栈顶
digester.addObjectCreate("teacher", Teacher.class);
digester.addSetProperties("teacher");
// 当遇到<teacher>的子元素<student>时创建一个Student对象,放入栈顶
digester.addObjectCreate("teacher/student", Student.class);
// 设置<student>的属性值,根据属性值调用相应的set方法
digester.addSetProperties("teacher/student");
// 当再次遇到<student>时创建一个Student对象,放入栈顶,
//同时调用栈次顶的addStudent方法
digester.addSetNext("teacher/student", "addStudent",
"com.javachen.xml.digester.Student");
try {
Teacher teacher = (Teacher) digester.parse(new File(
"src/com/javachen/xml/digester/student.xml"));
assertEquals(8, teacher.getStudents().size());
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
/**
* 子标签方式(设置Property方式一)
*/
@Test
public void testTwo() {
Digester digester = new Digester();
digester.setValidating(false);
// 设置栈顶
digester.push(new TeacherList());
digester.addObjectCreate("teachers/teacher", Teacher.class);
digester.addSetProperties("teachers/teacher");
digester.addObjectCreate("teachers/teacher/student", Student.class);
// digester.addSetProperties("teachers/teacher/student");
// 子标签方式设置属性方法之一,第三个参数是第二个参数所指方法的参数个数
digester.addCallMethod("teachers/teacher/student/name", "setName", 1);
digester.addCallMethod("teachers/teacher/student/age", "setAge", 1);
digester.addCallMethod("teachers/teacher/student/id", "setId", 1);
digester.addSetNext("teachers/teacher/student", "addStudent",
"com.javachen.xml.digester.Student");
digester.addSetNext("teachers/teacher", "addTeachers",
"com.javachen.xml.digester.Teacher");
try {
TeacherList teacher = (TeacherList) digester.parse(new File(
"src/com/javachen/xml/digester/teacher.xml"));
assertEquals(2, teacher.getTeachers().size());
assertEquals("java", teacher.getTeachers().get(0).getCourse());
assertEquals(8, teacher.getTeachers().get(0).getStudents().size());
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
/**
* 子标签方式(设置Property方式二)
*/
@Test
public void testThree() {
Digester digester = new Digester();
digester.setValidating(false);
// 设置栈顶
digester.push(new TeacherList());
digester.addObjectCreate("teachers/teacher", Teacher.class);
digester.addSetProperties("teachers/teacher");
digester.addObjectCreate("teachers/teacher/student", Student.class);
// 子标签方式设置属性方法之二
digester.addBeanPropertySetter("teachers/teacher/student/name");
digester.addBeanPropertySetter("teachers/teacher/student/age");
digester.addBeanPropertySetter("teachers/teacher/student/id");
digester.addSetNext("teachers/teacher/student", "addStudent",
"com.javachen.xml.digester.Student");
digester.addSetNext("teachers/teacher", "addTeachers",
"com.javachen.xml.digester.Teacher");
try {
TeacherList teacher = (TeacherList) digester.parse(new File(
"src/com/javachen/xml/digester/teacher.xml"));
assertEquals(2, teacher.getTeachers().size());
assertEquals("java", teacher.getTeachers().get(0).getCourse());
assertEquals(8, teacher.getTeachers().get(0).getStudents().size());
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
/**
* 子标签方式 (callMethod callParam方式)
*/
@Test
public void testFour() {
Digester digester = new Digester();
digester.setValidating(false);
digester.push(new TeacherList());
digester.addObjectCreate("teachers/teacher", "com.javachen.xml.digester.Teacher");
digester.addSetProperties("teachers/teacher");
// 当<student>时调用栈顶元素(Teacher)的addStudents却并不执行,
//等待addCallParam设置参数,3为参数个数,这里传入的参数是字符串。
digester.addCallMethod("teachers/teacher/student", "addStudent", 3);
digester.addCallParam("teachers/teacher/student/name", 0);
digester.addCallParam("teachers/teacher/student/age", 1);
// 这句之后即</student>才调用addStudents方法,并且如果再次遇到<student>重复。
digester.addCallParam("teachers/teacher/student/id", 2);
digester.addSetNext("teachers/teacher", "addTeachers",
"com.javachen.xml.digester.Teacher");
try {
TeacherList teacher = (TeacherList) digester.parse(new File(
"src/com/javachen/xml/digester/teacher.xml"));
assertEquals(2, teacher.getTeachers().size());
assertEquals("java", teacher.getTeachers().get(0).getCourse());
assertEquals(8, teacher.getTeachers().get(0).getStudents().size());
assertEquals("李世民2", teacher.getTeachers().get(1).getStudents()
.get(2).getName());
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
}
Recent Comments