Digester提供一种事件驱动的xml格式数据的处理方式,它根据xml的路径模式生成不同的对象并调用指定的方法设置对象的参数。Digester提供了比SAX更高级更友好的接口,更多的实现细节都被封装了,开发人员可以更专注于语义上的处理过程。
使用Digester需要加载commons-digester-*.*.jar包
使用Digester的基本步骤:
1、 创建一个org.apache.commons.digester.Digester类的实例
2、 设置初始化参数参数 如:
3、 (可选的)将需要初始化的对象放到Digester的对象栈中
4、 注册你希望触发事件的路径模式,如果一个路径模式注册了多个事件则事件按注册的列表顺序执行。
5、 调用digester.parse()
方法解析指定的xml文件。
Digester的属性及意义
classLoader 类加载器,当使用ObjectCreateRule
和 FactoryCreateRule
规则时使用
classLoader加载规则需要的类。如果不设置程序会调用线程类加载器或者使用加载
Digester时所使用的加载器。
errorHandler 定义自己的SAX ErrorHandler
,默认的把所有解析错误输出到日志,但是
Digester会继续进行解析。
namespaceAware 是否使用xml命名空间
ruleNamespaceURI 命名空间位置
rules 匹配规则
useContextClassLoader 是否使用上下文类加载器
validating 是否进行特点规则校验,默认执行格式良好校验
对象堆栈
通过xml文档结构,Digester会动态创建一个对象树。Digester最初开发的主要目的就是通过struts-config.xml
文件让struts实现自我配置。
Digester公开一个堆栈当xml元素满足某个模式是,就会调用注册的方法去创建一个对象,并放入对象堆栈中。常用的堆栈操作方法有:
clear() 清理堆栈
peek() 获取栈顶的对象
pop() 栈顶的对象出栈
push() 对象入栈
一般当遇到一个元素的起始标签是创建对应的对象,当处理元素的子元素时对象呆在栈中,直到遇见元素的结束元素将对象出栈。
在栈中每创建一个元素,就会用一个top-1位置的对象(对象的父对象)的方法将top对象赋给top-1对象,这样就可以明确各对象之间的从属关系。
一个简单的办法应用根元素对应的对象就是预先见将对象的持有者入栈,然后添加addSetNext方法将跟对象赋给持有对象。
JasperReport编译jrxml加载器的分析:
public class JRXmlLoader private Digester digester = null; private JasperDesign jasperDesign = null; public JRXmlLoader(Digester digester) { this.digester = digester; } public void setJasperDesign(JasperDesign jasperDesign) { this.jasperDesign = jasperDesign; } public JasperDesign loadXML(InputSource is) throws JRException { //将当前对象入栈,以便存储根元素生成的对象 digester.push(this); /* * 解析输入的xml文件流 * */ digester.parse(is); ...... return this.jasperDesign; } }
JRXmlDigesterFactory配置Digester匹配模式
public final class JRXmlDigesterFactory { /** * Configures the given digester for parsing jasperreport xml report definition files. */ public static void configureDigester(Digester digester) throws SAXException, ParserConfigurationException { // set a composite classloader that includes both the JR classloader // and the context classloader CompositeClassloader digesterClassLoader = new CompositeClassloader( JRXmlDigesterFactory.class.getClassLoader(), Thread.currentThread().getContextClassLoader()); digester.setClassLoader(digesterClassLoader); digester.setErrorHandler(new ErrorHandlerImpl()); digester.setNamespaceAware(true); digester.setRuleNamespaceURI(JRXmlConstants.JASPERREPORTS_NAMESPACE); /* * 注册创建jasperDesign的工厂 */ digester.addFactoryCreate("jasperReport", JasperDesignFactory.class.getName()); /* 将栈顶对象调用setJasperDesign方法放入紧邻的对象中 即之前的JRXmlLoader digester.push(this); */ digester.addSetNext("jasperReport", "setJasperDesign", JasperDesign.class.getName()); /* 将属性元素入栈 * */ digester.addRule("*/property", new JRPropertyDigesterRule()); /* 创建reportFont的对象通过 addFont将该对象赋给紧邻的对象 */ digester.addFactoryCreate("jasperReport/reportFont", JRReportFontFactory.class.getName()); digester.addSetNext("jasperReport/reportFont", "addFont", JRReportFont.class.getName()); ...... } }
JasperDesignFactory创建JasperDesign对象
public class JasperDesignFactory extends JRBaseFactory { /** * ObjectCreationFactory 定义的接口用于通过xml element创建对象 */ public Object createObject(Attributes atts) { /* * 创建jasperDesign对象,并取得对应的属性 */ JasperDesign jasperDesign = new JasperDesign(); //获取并设置属性name jasperDesign.setName( atts.getValue(JRXmlConstants.ATTRIBUTE_name)); jasperDesign.setLanguage( atts.getValue(JRXmlConstants.ATTRIBUTE_language)); ...... } }