刚刚学了一下Digester如何解析xml文件,所以记录下来,方便以后查看。
一般用来读取xml文件的工具包有DOM、SAX和JDOM等,但用过的人都知道,它们属于比较底层的API,写起来代码量很大,而且如果修改了xml文件的格式,代码也要做大幅度的改动。而使用Apache Jakarta的Digester,解析XML文件非常方便且不需要过多的关心底层的具体解析过程。Digester本来仅仅是Jakarta Struts中的一个工具,用于处理struts-config.xml配置文件。显然,将XML文件转换成相应的Java对象是一项很通用的功能,这个工具理应具有更广泛的用途,所以很快它就在Jakarta Commons项目(用于提供可重用的Java组件库)中有了一席之地。Digester由"事件"驱动,通过调用预定义的规则操作对象栈,将XML文件转换为Java对象。
工作原理如下: Digester底层采用SAX(Simple API for XML)析XML文件,所以很自然的,对象转换由"事件"驱动,在遍历每个节点时,检查是否有匹配模式,如果有,则执行规则定义的操作,比如创建特定的Java对象,或调用特定对象的方法等。此处的XML元素根据匹配模式(matching pattern)识别,而相关操作由规则(rule)定义。
如下xml代码,右边是左边元素对应的匹配模式:
例子1:
下面介绍解析xml文件的代码
下面是存放地址及编码的xml文件viewcache.xml(片段):
此xml文件分3层结构,分别为:
<viewcache>节点 其下包含1个<areas>节点
<areas>节点 其下包含多个<area>节点
<area>节点,其下包含各种信息节点 : 如:<id> 、<name>等。
我们的操作目标是把area中的信息节点的内容提取出来。
把每个<arrea>看做为一个对象,<area>中信息节点的内容为对象中的元素。
设定一个类Area.java 其内容如下:
- public class Area {
- private int id;
- private String name;
- private String areaType;
- private int parentId;
- private int ordering;
- private String zip;
- private String phoneArea;
- public int getOrdering() {
- return ordering;
- }
- public void setOrdering(int ordering) {
- this.ordering = ordering;
- }
- public String getAreaType() {
- return areaType;
- }
- public void setAreaType(String areaType) {
- this.areaType = areaType;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getParentId() {
- return parentId;
- }
- public void setParentId(int parentId) {
- this.parentId = parentId;
- }
- public String getZip() {
- return zip;
- }
- public void setZip(String zip) {
- this.zip = zip;
- }
- public String getPhoneArea() {
- return phoneArea;
- }
- public void setPhoneArea(String phoneArea) {
- this.phoneArea = phoneArea;
- }
- }
创建一个ViewCache类,用来保存解析后的所有对象:
- public class ViewCache {
- private List areaList = new ArrayList();
- public List getAreaList() {
- return areaList;
- }
- public void setAreaList(List areaList) {
- this.areaList = areaList;
- }
- // 供Digester调用的方法
- public void addArea(Area area) {
- this.areaList.add(area);
- }
- }
创建一个类AreaDigester,对xml文件进行解析:
- public class AreaDigester {
- public ViewCache digester() throws Exception {
- Digester digester = new Digester();
- digester.setValidating(false);
- digester.addObjectCreate("viewcache/areas", ViewCache.class);
- // 指明匹配模式和要创建的类
- digester.addObjectCreate("viewcache/areas/area", Area.class);
- // 设置对象属性,与xml文件对应,不设置则是默认
- digester.addBeanPropertySetter("viewcache/areas/area/id", "id");
- digester.addBeanPropertySetter("viewcache/areas/area/parentId", "parentId");
- digester.addBeanPropertySetter("viewcache/areas/area/name", "name");
- digester.addBeanPropertySetter("viewcache/areas/area/areaType", "areaType");
- digester.addBeanPropertySetter("viewcache/areas/area/ordering", "ordering");
- digester.addBeanPropertySetter("viewcache/areas/area/zip", "zip");
- digester.addBeanPropertySetter("viewcache/areas/area/phoneArea", "phoneArea");
- // 当移动到下一个标签中时的动作
- digester.addSetNext("viewcache/areas/area", "addArea");
- ViewCache vc = null;
- try {
- vc = (ViewCache) digester.parse("viewcache.xml");
- } catch (IOException e) {
- throw new Exception(e);
- } catch (SAXException e) {
- throw new Exception(e);
- }
- return vc;
- }
- }
调用AreaDigester的digester方法,即可把解析后的所有地址对象,存放在ViewCache的list中。
例子2:
要解析的xml文件books.xml如下:
- <?xml version="1.0" encoding="UTF-8" ?>
- <library name="alibaba图书馆">
- <book title ="thinking in java" author="xxx">
- <chapter>
- <no>第一章</no>
- <caption>第一章的标题</caption>
- </chapter>
- <chapter>
- <no>第二章</no>
- <caption>第二章的标题</caption>
- </chapter>
- </book>
- <book title="effective java" author="yyy">
- <chapter>
- <no>第一章</no>
- <caption>第一章的标题</caption>
- </chapter>
- </book>
- </library>
Library类如下:
- public class Library {
- private String name;
- private List<Book> bookList = new ArrayList<Book>();
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public List<Book> getBookList() {
- return bookList;
- }
- public void addBook(Book book) {
- bookList.add(book);
- }
- }
Book类如下:
- public class Book {
- private String title;
- private String author;
- private List<Chapter> chapters = new ArrayList<Chapter>();
- /**
- * 这个方法,用来演示xml的解析时用的另一种方式
- * @param title
- * @param author
- */
- public void setBookInfo(String title, String author) {
- this.title = title;
- this.author = author;
- }
- public void addChapter(Chapter chapter) {
- this.chapters.add(chapter);
- }
- public String getTitle() {
- return title;
- }
- public void setTitle(String title) {
- this.title = title;
- }
- public String getAuthor() {
- return author;
- }
- public void setAuthor(String author) {
- this.author = author;
- }
- public List<Chapter> getChapters() {
- return chapters;
- }
- public void setChapters(List<Chapter> chapters) {
- this.chapters = chapters;
- }
- }
Chapter类如下:
- public class Chapter {
- private String no;
- private String caption;
- public String getNo() {
- return no;
- }
- public void setNo(String no) {
- this.no = no;
- }
- public String getCaption() {
- return caption;
- }
- public void setCaption(String caption) {
- this.caption = caption;
- }
- }
解析xml的类如下:
- public class MainTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // 建立一个Digester对象
- Digester digester = new Digester();
- //指定它不要用DTD验证XML文档的合法性——这是因为我们没有为XML文档定义DTD
- digester.setValidating(false);
- // 从library标签开始解析,并新建一个Library对象做为根对象
- digester.addObjectCreate("library", Library.class);
- // 根据library标签属性值设置对象的属性,一次可以设置多个属性
- digester.addSetProperties("library");
- // 也可以用下面的方法,指定propertyName
- // digester.addSetProperties("library", "name", "name");
- // -----第1层元素开始
- digester.addObjectCreate("library/book", Book.class);
- //digester.addSetProperties("library/book");
- // 可以用以下三条语句代替
- digester.addCallMethod("library/book", "setBookInfo", 2);
- digester.addCallParam("library/book", 0, "title");
- digester.addCallParam("library/book", 1, "author");
- /**
- * addCallParam(String rule, int paraIndex,String attributeName)
- * 该方法与addCallMethod配合使用
- * int paraIndex:表明需要填充的方法形参序号,从 0 开始,方法由addCallMethod指定
- * String attributeName:指定标签属性名称
- */
- // -----第2层元素开始
- digester.addObjectCreate("library/book/chapter", Chapter.class);
- /** addBeanPropertySetter()是将子节点转换为对象的属性,这个方法还可以有第二个参数,当对象的属性名和子节点的名字不一样时用来指定对象的属性名
- 该方法的作用及使用方法类似于addSetProperties,只不过它是用String rule规则所指定标签的值(而不是标签的属性)来调用对象的setter*/
- digester.addBeanPropertySetter("library/book/chapter/no");
- // digester.addBeanPropertySetter("library/book/chapter/no", "no");
- /** addCallMethod(String rule,String methodName, int paraNumber) 方法
- * 同样是设置对象的属性,但是方式更加灵活,不需要对象具有setter
- * 当paraNumber = 0时,可以单独使用(表明为标签的值来调用),不然需要配合addCallParam方法
- */
- // digester.addBeanPropertySetter("library/book/chapter/caption");
- // 下面的方法,可以用来代替上一句,作用是一样的
- digester.addCallMethod("library/book/chapter/caption", "setCaption", 0);
- // addSetNext()是说在再次遇到匹配节点后, 调用当前对象(Chapter类的对象)的父对象(Book类的对象)的方法,方法参数是当前层元素的对象
- digester.addSetNext("library/book/chapter", "addChapter");
- // -----第2层元素结束
- digester.addSetNext("library/book", "addBook");
- // -----第1层元素结束
- try {
- // 解析XML文件,并得到ROOT元素
- Library library = (Library) digester.parse(MainTest.class.getResourceAsStream("books.xml"));
- System.out.println(" 图书馆: " + library.getName());
- System.out.println(" 共藏书: " + library.getBookList().size() + " 本 ");
- System.out.println(" ***************************** ");
- for (Book book : library.getBookList()) {
- System.out.println(" 书名: " + book.getTitle() + " 作者: " + book.getAuthor());
- System.out.println(" ------------------------------ ");
- // 显示章节
- System.out.println(" 共 " + book.getChapters().size() + " 章 ");
- for (Chapter chapter : book.getChapters()) {
- System.out.println(chapter.getNo() + ": " + chapter.getCaption());
- }
- System.out.println(" ------------------------------ ");
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (SAXException e) {
- e.printStackTrace();
- }
- }
- }
例子3:
Digester解析xml的规则,除了在java类中描述设置之外,还可以把解析规则放在xml文件中。以例子2中的代码为例,规则在books-rule.xml文件中,内容如下:(The DTD is distributed in the commons-digester.jar
. It can be found at org/apache/commons/digester/xmlrules/digester-rules.dtd,通过查看DTD文件,可以知道有哪些标签可以使用
)
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE digester-rules PUBLIC
- "-//Jakarta Apache //DTD digester-rules XML V1.0//EN"
- "digester-rules.dtd">
- <digester-rules>
- <object-create-rule pattern="library" classname="com.alibaba.chj.digester.Library" />
- <set-properties-rule pattern="library">
- <alias attr-name="name" prop-name="name" />
- </set-properties-rule>
- <pattern value="library/book">
- <object-create-rule classname="com.alibaba.chj.digester.Book" />
- <set-properties-rule />
- <pattern value="chapter">
- <object-create-rule classname="com.alibaba.chj.digester.Chapter" />
- <bean-property-setter-rule pattern="no" propertyname="no" />
- <bean-property-setter-rule pattern="caption" propertyname="caption" />
- <set-next-rule methodname="addChapter" />
- </pattern>
- <set-next-rule methodname="addBook" />
- </pattern>
- </digester-rules>
解析xml类的代码,修改为:
- public class MainTest {
- /**
- * @param args
- */
- public static void main(String[] args) {
- try {
- Digester digester = DigesterLoader.createDigester(DigesterXmlRuleTest.class.getResource("books-rule.xml"));
- Library library = (Library) digester.parse(DigesterXmlRuleTest.class.getResourceAsStream("books.xml"));
- System.out.println(" 图书馆: " + library.getName());
- System.out.println(" 共藏书: " + library.getBookList().size() + " 本 ");
- System.out.println(" ***************************** ");
- for (Book book : library.getBookList()) {
- System.out.println(" 书名: " + book.getTitle() + " 作者: " + book.getAuthor());
- System.out.println(" ------------------------------ ");
- // 显示章节
- System.out.println(" 共 " + book.getChapters().size() + " 章 ");
- for (Chapter chapter : book.getChapters()) {
- System.out.println(chapter.getNo() + ": " + chapter.getCaption());
- }
- System.out.println(" ------------------------------ ");
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (SAXException e) {
- e.printStackTrace();
- }
- }
- }
用于规则放在xml文件中,所以解析的类,显得更加简洁一些。
相关推荐
这个示例演示了如何使用Apache Commons Digester解析XML文件,将XML数据转换为Java对象。通过定义规则,我们可以轻松地处理复杂的XML结构,并将它们映射到Java对象模型中。这在处理大量配置数据或需要从XML文件加载...
标题“利用commons-digester解析XML”涉及到的是Java开发中的一种处理XML文档的工具——Apache Commons Digester。这个库提供了一种方便的方式来映射XML文档结构到Java对象,从而简化了XML数据的处理过程。 Apache ...
Apache Commons Digester库提供了一种规则驱动的方法来解析XML文档,并根据预定义的规则将XML数据映射到Java对象上。这个库在处理XML配置文件时特别有用,它允许开发者将XML结构转换为相应的Java对象结构,从而简化...
**Apache Commons Digester** 是一个Java库,它允许开发人员定义一套规则,这些规则可以解析XML文档,并根据这些规则在Java对象模型中创建和配置对象。这个库在处理XML到Java对象映射时非常有用,特别是在构建配置...
4. **解析XML**:使用`Digester`实例解析XML文档,它会按照规则自动创建和配置对象。 5. **处理结果**:解析完成后,Java对象结构已经构建完毕,可以进行后续的业务处理。 **许可证信息**:`commons-digester-1.7....
当 Digester解析到匹配的XML元素时,就会执行对应的Rule。例如,你可以定义一个Rule来创建一个新的Java对象,或者将XML属性值设置到已存在的对象上。 2. **RuleSet**: RuleSet是一组相关的Rule,它们共同作用于特定...
《Apache Commons Digester 2.0:解析XML的利器》 Apache Commons Digester是一个Java库,主要用于将XML文档解析成Java对象。这个库的核心功能是根据预定义的规则(Rule)来读取XML文档,然后根据这些规则进行一...
Commons-Digester是一个Java库,它提供了一组规则来解析XML文档,并将解析结果映射到Java对象。这个库在处理XML配置文件时特别有用,因为它可以自动化将XML元素和属性转换为对象的属性和方法调用。在给定的标题...
4. **示例**:可能包含一些示例代码,展示如何配置和使用Digester进行XML解析。 5. **许可文件**:Apache Commons Digester遵循Apache Software License 2.0,压缩包中应包含许可文件,阐述了使用、分发和修改该库...
我们无须了解SAX和DOM的解析过程,只要给Digester添加一些解析规则,就能对一个xml文件进行解析。Digester使用堆栈来保存xml节点(stack.push()方法),当该xml节点中嵌套的所有子节点解析完毕,该节点将被弹出...
Apache Commons Digester是一个强大的Java库,主要功能是解析XML文档,并根据预定义的规则将其转换为Java对象。在标题"commons-digester-2.0.jar.zip"中,我们看到的是这个库的一个特定版本——2.0,它被压缩成一个...
Digester提供了一种从XML文档创建Java对象结构的方式,它可以根据预定义的规则集(RuleSet)自动解析XML,并调用相应的JavaBean方法,实现XML到Java对象的映射。这个库特别适用于那些XML配置文件需要转化为Java对象...
digester必备的jar,XML解析专用
3. **Digest Process**:Digester解析XML文档的过程,按照规则集执行,将XML结构转化为Java对象。 ## 三、主要功能 1. **对象创建**:根据XML元素创建对应的Java对象。例如,每当解析到特定的XML标签时,可以创建...
然后,使用`Digester`类的`parse()`方法解析XML文档,这将触发规则并执行相应的动作。例如,一个简单的规则可能是在遇到XML文档中的"<employee>"元素时创建一个新的`Employee`对象,并在遇到子元素如"<name>"和...
标题中的"commons-digester"是指Apache Commons项目中的一个模块,专门用于XML解析和对象绑定。这个库提供了方便的方法来将XML文档解析成Java对象,它通过定义一系列规则(Rules)来实现XML到对象的映射,使得处理...
开发者通过研究这个源代码,可以了解到XML解析的实现细节,以及 Digester 如何帮助构建基于XML配置的应用程序,特别是对于理解Struts框架的工作原理非常有帮助。此外,这也可以作为一个学习Java设计模式和最佳实践的...