Digester : a java object builder based xml

在Java编程中,配置文件大多数都是用xml文件来组织的。所以在Java语言中处理xml的工具就特别多。

在java中解析XML的几种方式,应该都是知道的。在这些解析技术的基础之上,又发展了几种优秀Object/XML关联的技术,例如有一种对象绑定技术(JAXB),再例如Digester。这里就来简单的了解一下Digester技术。

如果说对Digester运用最为高超的应用,非Tomcat莫属了。Tomcat中几个重要的配置文件(如server.xml、web.xml、context.xml),都是使用Digester来完成xml到Java对象的转换的。

Digester只需要设置好相应的处理规定,就可以得到想要的对象结构。它的最大优点就是可以自定义各种处理规则。然而,如果不能明白Digester的设计原理,那你就只使用Digester给你提供的几种规则了。

Digester例子

Java对象设计:

package com.fjn.frame.digester.list;

public class XxObject {
    private String id;
    private String name;
    private int num;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return "id: " + id + "\tname: " + name + "\tnum: " + num;
    }
}

这个类没有任何的含义,只是我随便写的而已。

一个简单的XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<XxObjects>
    <XxObject id="id001" name="hello1" num="1" />
    <XxObject id="id002" name="hello2" num="2" />
    <XxObject id="id003" name="hello3" num="3" />
    <XxObject id="id004" name="hello4" num="4" />
    <XxObject id="id005" name="hello5" num="5" />
    <XxObject id="id006" name="hello6" num="6" />
    <XxObject id="id007" name="hello7" num="7" />
    <XxObject id="id008" name="hello8" num="8" />
    <XxObject id="id009" name="hello9" num="9" />
</XxObjects>

接下来的任务就是将这个XML文件转换为一个对象集合了。

package com.fjn.frame.digester.list;

import java.io.IOException;
import java.util.List;

import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.commons.digester3.Digester;
import org.junit.Test;
import org.xml.sax.SAXException;

public class Convertor {
    @Test
    public void test() throws ParserConfigurationException, SAXException,
            FactoryConfigurationError, IOException {
        SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
        Digester digester = new Digester(parser);
        digester.addObjectCreate("XxObjects", "java.util.LinkedList");

        digester.addObjectCreate("XxObjects/XxObject",
                "com.fjn.frame.digester.list.XxObject");
        digester.addSetProperties("XxObjects/XxObject");
        // digester.addSetNext("XxObjects/XxObject", "add");
        digester.addRule("XxObjects/XxObject", new AddToCollectionRule());

        List<XxObject> ret = digester.parse(Convertor.class
                .getResourceAsStream("XxObjects.xml"));
        for (XxObject obj : ret) {
            System.out.println(obj);
        }
    }
}

AddToCollectionRule规则是我自定义的规则:

package com.fjn.frame.digester.list;

import java.util.Collection;

import org.apache.commons.digester3.Rule;
import org.xml.sax.Attributes;

public class AddToCollectionRule extends Rule {
    @Override
    public void begin(String namespace, String name, Attributes attributes)
            throws Exception {
        Object top = this.getDigester().peek();
        Object o = this.getDigester().peek(1);
        if (o != null) {
            Collection colls = (Collection) o;
            System.out.println(top);
            colls.add(top);
        }
    }

}

程序运行结果:

id: id001	name: hello1	num: 1
id: id002	name: hello2	num: 2
id: id003	name: hello3	num: 3
id: id004	name: hello4	num: 4
id: id005	name: hello5	num: 5
id: id006	name: hello6	num: 6
id: id007	name: hello7	num: 7
id: id008	name: hello8	num: 8
id: id009	name: hello9	num: 9
id: id001	name: hello1	num: 1
id: id002	name: hello2	num: 2
id: id003	name: hello3	num: 3
id: id004	name: hello4	num: 4
id: id005	name: hello5	num: 5
id: id006	name: hello6	num: 6
id: id007	name: hello7	num: 7
id: id008	name: hello8	num: 8
id: id009	name: hello9	num: 9

使用Digester将xml转为java对象,就是这么简单。

使用起来如此简单,它是怎么做到的呢?

Digester设计原理

  如果是使用DOM解析的方式,我相信只要你了解DOM树,你就肯定能够完成这个轻松的任务,这也是程序员们更加容易接受DOM解析的原因。但是,设想一下,如果让你来将一个XML文件使用SAX解析的方式,转换为Java对象,你会怎么做呢?

我在看Digester的源码之前,就做过这样的设想。因为SAX解析的方式中,我们使用的最多的应当是startElement和endElement了。SAX解析是基于事件的,遇到一个开始元素,就执行startElement方法,遇到一个结束元素就执行endElement方法。

  一般来说一个XML元素就对应一个Java对象,XML元素的属性就对应的是Java对象的属性。遇到一个元素开始,就可以根据元素名称来创建出对象。根据元素的属性来设置对象的属性。这个了是很简单的,但是在end一个元素后,也就是对象创建完成后,怎么来存储呢?总不能解析完成,生成了很多对象,我一个也拿不到,那解析它有何用呢。可以考虑一个复杂的XML,例如tomcat的server.xml文件,Server\Service\Engine等有对象是嵌套的,创建一个对象Service后,怎么将它设置到Server中呢?创建一个对象Engine后,怎么将它设置到Service中呢。完成这个工作,就必然要使用到一个数据结构:Stack。如果你能想到这里,Digester你就学会了80%了。

Java对象在startElement中创建并入栈,在endElement中完成所有操作并出栈。

例子说明

在上面的例子中,解析到根元素时,会创建出一个LinkedList,然后入栈。因为没有到结束元素,所以它肯定会在栈里,并且是在最下面。然后是解析每个XxObject了。在解析XxObject元素时,都要有3个操作,它们是依次进行的:

1)创建XxObject对象。入栈,那么这个对象肯定是在栈顶了。

2)设置属性。Digester使用的是BeanUtils工具来完成属性的设置的,所以java类在设计时, 是需要 getter和setter的。

3)调用我自定义的AddToCollection规则了。执行这个规则也很简单,取得当前对象(栈顶元素),再取出从栈顶起第二个元素,也就是LinkedList。然后就可以添加到集合中了。

4)endElement,对象出栈,栈中只剩下LinkedList对象。

最后遇到XxObejcts的end,它就是解析到最后一刻时栈底。返回的什就是栈底对象。所以结果就是一个List了。

我自定义的那个AddToCollection规则,只是想用于说明如何Digester的原理,以及如何使用自定义规则。其实像这个的常用的规则,Digester已经定义好了,SetNetRule。

到这里,这篇文章的主要内容已经说完了。至于如何使用Digester中的各种Rule,还需要靠自己去了解了。

下面附加一张类图:

时间: 2024-08-27 10:40:25

Digester : a java object builder based xml的相关文章

Java与XML的故事二:XML与Java Object互相转换

XML文件和Java对象转换是一件非常简单的事情,有了annotation的java文件和XML schema XSD文件,可以简单的通过JAXB API来实现XML与Java Object转换 marshaller Java to XML Exception is not display here prviate static javax.xml.bind.JAXBContext jaxbCtx = null; private static Schema schema = null; stat

JAXB XML到java object的转换

JAXB是Java Architecture for XML Binding的缩写.使用JAXB注解将Java对象转换成XML文件.在这篇教程中,我们将会展示如何使用JAXB来做以下事情: 1. marshall 将java对象转化成xml文件 2. unmarshalling 将xml内容转换成java对象 JAXB 注解(Annotation) 如果一个对象需要被转换成XML文件,或者从XML文件中生成,该对象需要用JAXB注解来标注.这些注解光凭名字就知道是什么意思了.具体可参考官网:ja

Java Object Oriented Programming concepts

Introduction This tutorial will help you to understand about Java OOP'S concepts with examples. Let's discuss about what are the features of Object Oriented Programming. Writing object-oriented programs involves creating classes, creating objects fro

Java Jaxb JavaBean与XML互转

1.Jaxb - Java Arcitecture for XML Binding 是业界的一个标准,是一项可以根据XML Schema产生Java类的技术. Jaxb2.0是Jdk1.6的组成部分.不需要在第三方Jar包的支持下即可完成Xml与JavaBean的相互转换. 2.重要概念: ·JAXBContext类,是应用的入口,用于管理XML/Java绑定信息. ·Marshaller接口,将Java对象序列化为XML数据. ·Unmarshaller接口,将XML数据反序列化为Java对象

利用JAXB实现java实体类和xml互相转换

1.应用场景 在使用WebService实现数据上传下载,数据查询时,可以利用JAXB实现java实体类和xml互相转换 2.Demo 2.1 student.java 实体类,包含list(set同理).map.Teacher.Date 类型的属性 package jaxb; import java.util.Date; import java.util.List; import java.util.Map; import javax.xml.bind.annotation.XmlAccess

Java读取、创建xml(通过dom方式)

创建一个接口 XmlInterface.java public interface XmlInterface {         /**         * 建立XML文档         * @param fileName 文件全路径名称         */         public void createXml(String fileName);         /**         * 解析XML文档         * @param fileName 文件全路径名称       

Java使用XPath查询XML中的元素

使用java中的xpath语法查询xml中元素 1.查询的xml文件为student.xml文件 <?xml version="1.0" encoding="UTF-8" ?><students> <student class="1201">  <name>李小离</name>  <sex>男</sex>  <age>25</age> &l

java使用dom4j解析xml

目标:将指定XML进行解析,以键=值的方式返回指定节点下的数据 所需要的jar包:dom4j1.6.1.jar.jaxen-1.1.jar <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://s

Java读取、创建xml(通过dom方式)文档版

Java读取.创建xml(通过dom方式) 1.创建一个DocumentBuilderFactory的实例dbf DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 2.通过dbf创建一个DocumentBuilder 出来db  DocumentBuilder db = dbf.newDocumentBuilder(); 3.利用db解析文档赋值给Document对象  Document document = d