使用Digester解析XML文档

来源:互联网 发布:沪港通交易数据 编辑:程序博客网 时间:2024/06/11 18:53

一、Digester是一个将配置文件转换为Java对象的工具

Digester是一个将配置文件转换为Java对象的工具,当一些 XML中特定的属性将会触发一些被称为 rules 的动作

 

commons-digester是apache open source组织的一组将XML数据装载成java object API。它是使用了SAX解析器,当解释到某个XML Element标签时,触发同该标签相关的一组动作,在动作中而完成javaobject的创建、加工、方法调用等操作。

 

apache小组的jakarta项目下有许多知名的基于java的开放源码子项目。

包括tomcat,ant,log4j,struts,commons等等。

 

Digester是jakartacommons里面的一个包

 

主要的开发人员是:CraigMcClanahan。Craig McClanahan

 

使用Digester,需要jakarta下的如下包:BeanUtils, Collections, Logging.Digester的下载地址:
http://apache.linuxforum.net/dist/jakarta/commons/digester/binaries/目前版本为1.4

二、三个核心概念:

①:元素匹配规则Pattern(有点类似于XPath)→找出XML配置文件中对应的部分准备处理

当处理程序找到pattern后就会调用和这个相联系的rule(处理规则),

当pattern匹配他就会得到调用默认的规则由org.apache.commons.digester.Rule的子类创建ObjectStack (对象栈)。

②:处理规则Rule;   →指定一个处理规则来处理这些待处理的元素。digester模块已经预定了不少处理规则,自定义的处理规则可以通过扩展org.apache.commons.digester.rule类来实现。

③:对象栈     →按照解析的层次关系,将XML配置文件中解析出的对象依次入栈

三、Digester解析的步骤:

①:创建一个Digester类的实例;

②:指定其使用的Pattern及Rule;

③:传递一个引用XML文件的对象参数到parse()方法;

try{

 Fileinput=newFile(args[0]);

 Filerules=newFile(args[1]);

 //创建digester对象并指定解析规则

 Digesterdigester=DigesterLoader.createDigester(rules.toURL());

 //传递配置文件引用input到digester进行解析,解析出的对象就是对应的对象;

 Catalogcatalog=(Catalog)digester.parse(input);

 System.out.println(catalog.toString());

}catch(Exceptionexc){

 exc.printStackTrace();

}

配置文件input如下:

…………

Pattern规则文件如下:

…………

四、使用Digester的方法:

①:定制配置文件

②:写对象的Pattern文件

③:写与对象匹配的对象类,如上文中的Catalog、Book、Magazine类

④:生成Digester对象实例,指定规则及输入,进行解析

注意:在③中,如果Catalog与Magazine对象有关联(有Catalog.addMagazine()方法),需要用模式指令set-next-rule,

该指令的机理源码如下:

     if(useExactMatch){      

          MethodUtils.invokeExactMethod(parent,methodName,

              newObject[]{child},paramTypes);              

      }else{      

          MethodUtils.invokeMethod(parent,methodName,

              newObject[]{child},paramTypes);      

       }

child,与parent都是Digester对象栈中的元素,parent先入栈,child后入栈,可见set-next-rule所指定的方法为parent的方法。所以,在写模式文件时,需要注意,addMagazine()方法是需要写在Magazine元素内。

五、标准规则的简短描述:

A、创建:

ObjectCreateRule:使用默认构造函数来创建一个指定类的对象并且把它推入栈中;当元素结束时弹出。被初始化的类可能通过一个类对象或者fully-qualified类名来给出。

FactoryCreateRule:使用一个指定的工厂类来创建一个对象并且将它推入栈内。这可能对于那些没有提供默认构造函数的类更加有用。工厂类必须实现

org.apache.commons.digester.ObjectCreationFactory接口。

B、属性设置

SetPropertiesRule:使用指定的XML元素属性的值来设置一个或几个顶级bean的名字属性。

Attribute名和 property 名以字符数组的形式被传递给这个规则。(典型的XML结构:<articlepage="10">)。

BeanPropertySetterRule:设置指定的顶级bean的属性为包含在当前XML元素中的字符数据。(例如:<page>10</page>

SetPropertyRule:设置一个顶级bean属性。属性名和这个属性将设置的值都通过当前XML元素的属性给出。(例如:<articlekey="page" value="10" />)

 

C、父/子管理

SetNextRule:弹出栈顶对象然后把它传给指定的直接下级对象的方法。通常被用来把一个完成的bean插入到它的父亲节点。

SetTopRule:传递栈中的第二层对象给顶层对象。如果子对象扩展了setParent方法儿不是其他方法,它是有用的。

SetRootRule:调用一个栈底的对象的方法,把栈顶对象作为一个参数传递。

D、任意方法调用

CallMethodRule:调用顶级bean任意指定的方法。方法可能带有任意个数的参数。参数的值通过后续的CallParamRule程序给出。

CallParamRule:代表了方法的参数值。参数值可能从指定XML元素属性取得,也可能从当前元素的原始字符数据取得。这个规则要求参数列表中参数的位置被一个整数索引指定。

六Digester 的处理过程 (Rule, pattern, Object Stack)

建立一个新的对象

 

创建响应的规则的方法:

void addObjectCreate(java.lang.Stringpattern,java.lang.String className,java.lang.String attributeName)

 

建立调用 Method

void addCallMethod(java.lang.Stringpattern, java.lang.String methodName, int paramCount)

 

建立调用 Method 传入的参数

void addCallParam(java.lang.Stringpattern, int paramIndex)

 

XML 解析

java.lang.Object parse(java.lang.Stringuri) throws java.io.IOException,org.xml.sax.SAXException

七、例子一:一个简单的例子


有一个如下的xml:user.xml

<users>

         <name>zhaofeng</name>

         <pass>88378100</pass>

</users>

 

有一个如下的javaObject:BaseObject

public class BaseObject {

         privateString name = "";

         privateString pass = "";

         /**

         *Returns the name.

         *@return String

         */

         publicString getName() {

                   returnname;

         }

 

         /**

         *Returns the pass.

         *@return String

         */

         publicString getPass() {

                   returnpass;

         }

 

         /**

         *Sets the name.

         *@param name The name to set

         */

         publicvoid setName(String name) {

                   this.name= name;

         }

 

         /**

         *Sets the pass.

         *@param pass The pass to set

         */

         publicvoid setPass(String pass) {

                   this.pass= pass;

         }

 

         publicvoid setInfo(String name,String pass){

                   this.name= name;

                   this.pass= pass;

 

         }

 

         publicvoid info() {

                   log("name:"+ name + "...pass :" + pass);

         }

 

         privatevoid log(String str) {

                   System.out.println(str);

         }

}

 

解析xml文件:Test.java

现在我们要把user.xml里面的内容解析为一个BaseObject.

import org.apache.commons.digester.Digester;

 

public class Test {

 

         publicvoid parse() {

        //创建Digester对象               

                   Digesterdigester = new Digester();

        //创建一个对象BaseObject

                   BaseObjectobj = new BaseObject();

                   try{

                        // 当遇到<users>时创建一个BaseObject对象,并且进入对象栈(入栈,成为栈顶元素)

digester.addObjectCreate("users", BaseObject.class);

                   //调用对象的方法setName并把users/name节点的值作为对象方法的参数            

                            digester.addCallMethod("users/name","setName", 0);

                            digester.addCallMethod("users/pass","setPass", 0);

                            /*下面是调用setInfo(String,String)设置信息的使用

                            *digester.addObjectCreate("users","com.henry.test.digester.BaseObject");

                            *digester.addCallMethod("users","setInfo",2);

                            *digester.addCallParam("users/name",0);

                            *digester.addCallParam("users/pass",1);

                            */

                 //上面的两段代码功能一样都是使用反射实现对象的创建和方法的调用

                 //第二段是一个方法有多个参数的情况

                            obj=(BaseObject)(digester.parse("user.xml"));

                            obj.info();

                   }catch (Exception ex) {

                            System.out.println(ex.getMessage());

                   }

         }      

        

         publicstatic void main(String[] args) {

                   Testp = new Test();

             p.parse();

         }

}

 

八、例子二:一个经典的例子

1. XML文件

在工程目录下新建一个XML文件,示例使用module.xml,内容见下:

 

<?xml version="1.0"encoding="gb2312" ?>

<quasar_module>

         <!--模块信息-->

         <module_info>

                   <name>Skyhome</name>

                   <description>theweb site system of www.skyinn.org </description>

                   <version>2.0.1</version>

                   <author>l_wakler</author>

                   <mail>walker@skyinn.org </mail>

                   <update_time>2003-04-30</update_time>

         </module_info>

         <!--Action映射信息-->

         <action_mappings>

                   <actionname="home" requestPath="/Home"actionClass="org.skyinn.action.GlobalAction"></action>

                   <actionname="forum" requestPath="/Forum"actionClass="org.skyinn.action.ForumAction"></action>

         </action_mappings>

</quasar_module>

 

2. 解析XML文档

Digester的使用相当简单,请参看如下的SampleDigester类中的注释,这里不再拗述:

 

/*============================================================

 *Copyright:www.skyinn.org (c) 2002 - 2003 All rights reserved.

 *File:org.skyinn.quasar.config.SampleDigester

 *Inculde:SampleDigester

 * ModifyRecords

 * Date              Author         Content

 *=============================================================

 *2003-5-1          walker        create class

 *============================================================*/

package org.skyinn.quasar.config;

 

import org.apache.commons.digester.Digester;

import org.xml.sax.SAXException;

import org.skyinn.quasar.action.ActionMapping;

 

import java.io.IOException;

 

/**

 * Digester解析XML示例程序。

 * <p>

 * @authorwalker(walker@skyinn.org)

 * <p>

 *<strong>参考文献:</strong><p>

 * <ahref="http://www.onjava.com/pub/a/onjava/2002/10/23/digester.html"target="_blank">Learning and Using JakartaDigester</a><p>

 * <ahref="http://developer.ccidnet.com/pub/disp/Article?columnID=340&articleID=33259&pageNO=1"target="_blank">用Digester简化XML配置文件处理</a>

 */

public class SampleDigester{

 

    privateString configFile;

 

    publicvoid setConfigFile(final String configFile){

       this.configFile = configFile;

    }

 

    /**

     * 开始解析。

     *<p>

     * 在本方法,new一个Digester的实例,并将本类(SampleDigester)的实例压入

     *Digester的处理堆栈,调用Digester的addCallMethod方法将XML文件中的特定

     * 节点与处理方法联系起来,并吊桶addCallParam方法设置参数,随后解析给定的XML

     * 文件。

     *@throws IOException IO异常

     *@throws SAXException SAX异常

     */

    publicvoid run() throws IOException, SAXException{

        //新建Digester实例

       Digester digester = new Digester();

        //将本类(SampleDigester)的实例压入Digester的处理堆栈

       digester.push(this);

        /* 调用Digester的addCallMethod方法将XML文件中的特定节点与处理方法联系起来

                    * quasar_module/module_info 为XML文件中的节点路径:<quasar_module><module_info>...

         *addModuleInfo 为本类中的一个方法(见下),即当碰到<quasar_module><module_info>节点时

         * 调用addModuleInfo方法,6表示该方法用六个参数,

         */

       digester.addCallMethod("quasar_module/module_info","addModuleInfo", 6);

        //逐个设置参数,第一个参数的索引为0

       digester.addCallParam("quasar_module/module_info/name", 0);

       digester.addCallParam("quasar_module/module_info/description",1);

       digester.addCallParam("quasar_module/module_info/version", 2);

       digester.addCallParam("quasar_module/module_info/author", 3);

       digester.addCallParam("quasar_module/module_info/mail", 4);

       digester.addCallParam("quasar_module/module_info/update_time",5);

        //This method starts the parsing of the document.

       digester.parse(this.configFile);

    }//endrun()

 

    /**

     * 添加模块信息。

     *<p>

     * 本方法仅将XML文件中的内容简单输出,实际应用中可以将获得的信息进行进一步的处理。

     *

     * @paramname 名字

     * @paramdescription 描述

     * @paramversion 版本

     * @paramauthor 作者

     * @parammail EMAIL

     * @paramupdateTime 更新时间

     */

    publicvoid addModuleInfo(final String name,

                              final Stringdescription,

                              final Stringversion,

                              final Stringauthor,

                              final Stringmail,

                             final StringupdateTime){

       //output

       System.out.println("name=" + name + ",description="+ description

                            +",version=" + version + ",author=" + author

                            +",mail=" + mail + ",updateTime=" +updateTime);

    }//endaddModuleInfo()

 

    /**

     * 添加Action映射。

     *<p>

     * 本方法仅简单输出了传入的ActionMapping的信息,在具体应用中可将其加入系统Action映射集合中。

     * @paramactionMapping Action映射

     */

    publicvoid addActionMapping(final ActionMapping actionMapping){

       System.out.println(actionMapping);

    }

 

    publicstatic void main(String[] args){

       SampleDigester sd = new SampleDigester();

       sd.setConfigFile("module.xml");

        try{

           sd.run();

           sd = null;

        }catch(Exception e){

           e.printStackTrace();

        }

 

       //__________________________________________

        //演示另一种解析方法

       Digester digester = new Digester();

       digester.setValidating( false );

        //生成本类实例

       digester.addObjectCreate( "quasar_module/action_mappings",SampleDigester.class);

        //生成ActionMapping实例

       digester.addObjectCreate("quasar_module/action_mappings/action",ActionMapping.class);

        //获取属性值,并将其存入ActionMapping实例

       digester.addSetProperties("quasar_module/action_mappings/action","name","name");

       digester.addSetProperties("quasar_module/action_mappings/action","requestPath","requestPath");

       digester.addSetProperties("quasar_module/action_mappings/action","actionClass","actionClass");

        //调用SampleDigester的addActionMapping方法

       digester.addSetNext("quasar_module/action_mappings/action","addActionMapping");

        try{

           digester.parse("module.xml");

       }catch(Exception e){

           e.printStackTrace();

        }

   }//end  main()

 

}//EOC SampleDigester

3、ActionMapping类

package org.skyinn.quasar.action;

 

public class ActionMapping {

 

           private String name;

           private String actionClass;

           private String requestPath;

          

           public String getName() {

             return name;

           }

 

           public void setName(String name) {

             this.name = name;

           }

 

           public String getActionClass() {

             return actionClass;

           }

 

           public void setActionClass(StringactionClass) {

             this.actionClass = actionClass;

           }

           public String getRequestPath() {

             return requestPath;

           }

 

           public void setRequestPath(String requestPath){

             this.requestPath = requestPath;

           }    

 

           private void prints(String s) {

             System.out.println("    " + s);

           }

 

           public void print(String s) {

             prints(s + "---name=" + name +",actionClass=" + actionClass + ",requestPath=" + requestPath);

           }

}

 

0 0
原创粉丝点击