Apache Commons Digester


简化xml文件处理,它依赖的组件:BeanUtils、Logging、Collections。


基本概念


1.在Digester的内部采用SAX来解析XML文件。为了能够正确的使用它,必须在解析之前进行相应的设置。同时,在解析xml文件的过程中,它使用Stack来保存和检索这个期间产生的对象。


2.为了简化使用,它通过匹配模式来定位要解析的xml标签。匹配模式的例子如下:


xml文件:


<?xml version="1.0"?>


<students>


<student>


<name>Java Boy</name>


<course>JSP</course>


</student>


<student>


<name>Java Girl</name>


<course>EJB</course>


</student>


</students>


每个标签与相应的匹配模式对应如下表:


标签


匹配模式


<students>


students


<student>


students/student


<name>


students/student/name


<course>


students/student/course


如果将xml文件结构视为一颗树的话,那么每个标签的匹配模式就是从根元素到这个元素的路径。除了使用具体的标签,还可以使用通配符。


3.使用匹配模式可以很方便的定位需要处理的元素,为了处理这些元素,需要定义处理规则。规则在匹配模式被找到时起作用。所有的规则都是从org.apache.commons.digester.Rule派生的。所有已定义的Rule对象,可以在org.apache.commons.digester中找到。常用的规则:


-ObjectCreate,创建对象实例。


-SetProperties,将标签属性(Attribute)与要创建的对象的属性相关联。


-BeanPropertySetter,将标签所包含标签与要创建的对象的属性相关联。


-SetNext,设置遇到下一个标签时的动作。


-CallMethod,设置当匹配模式被找到时要调用的方法。


-CallParam,设置对应的callMethod中指定方法所需要的参数值。


基本使用


以正确的顺序调用Digester方法是成功使用Digester处理XML文件的关键。使用步骤如下:


1.创建org.apache.commons.digester.Digester实例并配置,包括设置实现Digester Rule的对象。


2.使用Digester的push方法在Digester使用的stack中放置一个初始对象。在解析xml文件的过程中,Digester使用stack来保存它所找到的对象。第一个对象在遇到第一个标签时被放置到stack中,当最后一个标签处理完毕时被弹出。为了最后能检索到这个对象,因此需要一个初始对象来保留一个指向它的引用。


3.注册匹配模式和rule。


4.调用parse来解析xml文件。


使用举例


1.简单例子,从一个xml文件中创建对象。


XML文件:


<?xml version="1.0" encoding="UTF-8"?>


<students>


<student>


<name>Java Boy</name>


<course>JSP</course>


</student>


<student>


<name>Java Girl</name>


<course>EJB</course>


</student>


</students>


要创建的对象:


public class Student {


private String name;


private String course;


……


}


解析:


public class DigesterStudy {


private Vector students;


public DigesterStudy(){


students= new Vector( 5);


}


public static void main(String[] args) {


DigesterStudy ds= new DigesterStudy();


ds.digest();


}


public void digest(){


//创建实例


Digester digester= new Digester();


//将初始对象压入digester的stack


digester.push( this);


//指明匹配模式和要创建的类


digester.addObjectCreate( "students/student", Student.class);


//设置对象属性


digester.addBeanPropertySetter( "students/student/name");


digester.addBeanPropertySetter( "students/student/course");


//当移动到下一个标签中时的动作


digester.addSetNext( "students/student", "addStudent");


try {


//解析


DigesterStudy ds= (DigesterStudy)digester.parse( getClass()


.getClassLoader()


.getResourceAsStream( "students.xml"));


System.out.print( ds);


} catch (Exception e) {


e.printStackTrace();


}


}


public void addStudent( Student student){


students.add( student);


}


public String toString(){


return students.toString();


}


}


2.复杂例子,从xml文件中创建相互之间有关系的对象。


XML文件:


<?xml version="1.0" encoding="UTF-8"?>


<academy name="JAcademy" >


<student name="JavaBoy" division="A">


<course>


<id>C1</id>


<name>JSP</name>


</course>


<course>


<id>C2</id>


<name>Servlets</name>


</course>


</student>


<student name="JavaGirl" division="B">


<course>


<id>C3</id>


<name>EJB</name>


</course>


</student>


<teacher name="JavaGuru">


<certification>SCJP</certification>


<certification>SCWCD</certification>


</teacher>


<teacher name="JavaMaster">


<certification>OCP</certification>


<certification>SCJP</certification>


<certification>SCEA</certification>


</teacher>


</academy>


要创建的对象:


public class Academy {


private String name;


private Vector students;


private Vector teachers;


……


}


public class Student {


private String name;


private String division;


private Vector courses;


……


}


public class Course {


private String id;


private String name;


……


}


public class Teacher {


private String name;


private Vector certifications;


……


}


其中的<certification>在程序中对应一个字符串,故而没有列出。


解析:


public void digest(){


Digester digester= new Digester();


//注意,此处并没有象上例一样使用push,是因为此处从根元素创建了一个对//象实例


digester.addObjectCreate( "academy", Academy.class);


//将< academy >的属性与对象的属性关联


digester.addSetProperties( "academy");



digester.addObjectCreate( "academy/student", Student.class);


digester.addSetProperties( "academy/student");



digester.addObjectCreate( "academy/student/course", Course.class);


digester.addBeanPropertySetter( "academy/student/course/id");


digester.addBeanPropertySetter( "academy/student/course/name");


digester.addSetNext( "academy/student/course", "addCourse");



digester.addSetNext( "academy/student", "addStudent");



digester.addObjectCreate( "academy/teacher", Teacher.class);


digester.addSetProperties( "academy/teacher");


//当遇到academy/teacher/certification时,调用addCertification


digester.addCallMethod( "academy/teacher/certification",


"addCertification", 1);


//设置addCertification的参数值,此处的0表示这个元素体的第一个值


//为参数值传入addCertification。在此处,即为<certification>的值。


//(因为就只有一个)


digester.addCallParam( "academy/teacher/certification", 0);


digester.addSetNext( "academy/teacher", "addTeacher");


try {


Academy a= (Academy)digester.parse( getClass()


.getClassLoader()


.getResourceAsStream( "students.xml"));


System.out.print( a);


} catch (IOException e) {


// TODO Auto-generated catch block


e.printStackTrace();


} catch (SAXException e) {


// TODO Auto-generated catch block


e.printStackTrace();


}


}


3.从配置文件中创建Digester,通过DigesterLoader可以从配置文件中创建Digester实例,从而省去类似于上例手工配置Digester的代码。


Digester的配置文件,对应上例的配置文件如下:


<?xml version="1.0"?>


<digester-rules>


<pattern value="academy">


<object-create-rule classname="Academy" />


<set-properties-rule />


<pattern value="student">


<object-create-rule classname="Student" />


<set-properties-rule />


<pattern value="course">


<object-create-rule classname="Course" />


<bean-property-setter-rule pattern="id"/>


<bean-property-setter-rule pattern="name"/>


<set-next-rule methodname="addCourse" />


</pattern>


<set-next-rule methodname="addStudent" />


</pattern>


<pattern value="teacher">


<object-create-rule classname="Teacher" />


<set-properties-rule />


<call-method-rule pattern="certification" methodname="addCertification"


paramcount="1" />


<call-param-rule pattern="certification" paramnumber="0"/>


<set-next-rule methodname="addTeacher" />


</pattern>


</pattern>


</digester-rules>


使用配置文件之后,上例的代码变为:


Digester digester = DigesterLoader.createDigester(


this.getClass().getClassLoader().getResource("academyRules.xml"));


Academy a= (Academy)digester.parse( getClass()


.getClassLoader().getResourceAsStream( "students.xml"));

转载自:http://ronxin999.blog.163.com/blog/static/42217920201152352429141/