Digester学习笔记(二)转载
为便于理解,将笔记的内容结构作了一些调整。
对象栈
对digester技术最普通的应用,是用来动态创建一个由Java对象构成的树结构,各对象的属性以及对象间的关系,基于XML文档的内容来设置(XML文档就是一棵树)。为实现这种应用,Digester提供了一个对象栈,以供在相关的模板识别后被激活的处理规则操作。此栈的基本操作包括:
- clear(),清空栈的内容
- peek(),返回对栈顶对象的引用
- pop(),将栈顶对象弹出并返回
- push(),将一个新的对象压入栈顶
用栈的原因,就是当识别出一个XML元素的“开始”时,将相关对象生成并压入栈顶,这个对象在处理该元素的子元素的过程中一直在栈中,当所有子元素都处理完后,解析器遇到这个元素的“结束”时,则弹出此对象,并进行相关的处理。
如何描述对象间的关系呢?将栈顶的对象做为一个参数,传递给第二栈顶(即先于栈顶对象入栈的那个对象,在栈顶对象的下面)的一个方法,就可以简单地建立起一种“父子关系”,从而可以简单地建立起1:1的关系(第二栈顶对象与栈顶对象之间)和1:N的关系(第二栈顶对象不动,N次压栈顶弹栈顶对象).
如果取得生成的第一个对象呢?可以让parse()方法返回,或者在调用parse()方法前,先行压入一个对象,在parse()方法结束后弹出这个对象,则其子对象即为我们想要的第一个对象。
日志(logging)
日志是一个调试Digester规则集的非常重要的工具,它可以记录非常丰富的信息,因它在使用Digester之前有必要了解日志是如何工作的。
Digester使用Jakarta Commons Logging,这个模块并不是具体的日志实现,而只是一个可设置的接口。可以设置它将各种日志信息传递它自身带的基本记录器,或者传递给其它的更复杂的日志工具。具体请参考commons logging的文档,或Jakarta Commons Logging学习笔记
Digester主要使用两个记录器:
- SAX相关的信息,被送往org.apache.commons.digester.Digester.sax记录器,记录了Digester收到的SAX的事件的信息。
- 其它的所有信息,都被送往org.apache.commons.digester.Digester记录器,这个记录器在调试Digester时打开而在产品中常将其关闭
假定用commons logging自带的基本日志工具,并以DEBUG级别记录Digester调试信息以及INFO级别记录SAX事件信息,则对logging的配置文件设置如下:
Digester包中的例子
<address-book>
<person id="1" category="acquaintance" try="would be ignored">
<name>Gonzo</name>
<email type="business">gonzo@muppets.com</email>
<gender result="the whole tag would be ignored">male</gender>
</person>
<person id="2" category="rolemodel">
<name>Kermit</name>
<email type="business">kermit@muppets.com</email>
<email type="home">kermie@acme.com</email>
</person>
</address-book>**********Person.java************
import java.util.HashMap;
import java.util.Iterator;
public class Person {
private int id;
private String category;
private String name;
private HashMap emails = new HashMap();
//下面的两个方法的名字中set以后的部分,与<person>的属性名字对映。当从xml文件中识别出<person>的属性时,如果有要求(即调用过addSetProperties方法),Digester会依据这种对映关系自动调用相应的方法。
public void setId(int id) {
this.id = id;
}
public void setCategory(String category) {
this.category = category;
}
//对name而言,因为其值来自<name>标签的内容而非属性值,需要用addCallMethod指定识别<name>后的要调用此方法(想自动调用也要可以,需要addBeanPropertySetter,参见第下一个例子)。
public void setName(String name) {
this.name = name;
}
//同name,此时还要一一指定addEmail的参数值的来源。
public void addEmail(String type, String address) {
emails.put(type, address);
}
public void print() {
System.out.println("Person #" + id);
System.out.println(" category=" + category);
System.out.println(" name=" + name);
for(Iterator i = emails.keySet().iterator(); i.hasNext(); ) {
String type = (String) i.next();
String address = (String) emails.get(type);
System.out.println(" email (type " + type + ") : " + address);
}
}
}
**********AddressBook.java***********
import java.util.LinkedList;
import java.util.Iterator;
public class AddressBook {
LinkedList people = new LinkedList();
public void addPerson(Person p) {
people.addLast(p);
}
public void print() {
System.out.println("Address book has " + people.size() + " entries");
for(Iterator i = people.iterator(); i.hasNext(); ) {
Person p = (Person) i.next();
p.print();
}
}
}
************AddressBookDigester*********
import org.apache.commons.digester.Digester;
/**
* Usage: java Example1 example.xml
*/
public class AddressBookDigester {
public static void main(String[] args) {
if (args.length != 1) {
usage();
System.exit(-1);
}
String filename = args[0];
// 创建一个Digester实例
Digester d = new Digester();
// 创建AddressBook实例,并将其压入栈顶。
AddressBook book = new AddressBook();
d.push(book);
// 增加规则
addRules(d);
// 处理输入的xml文件
try {
java.io.File srcfile = new java.io.File(filename);
d.parse(srcfile);
}
catch(java.io.IOException ioe) {
System.out.println("Error reading input file:" + ioe.getMessage());
System.exit(-1);
}
catch(org.xml.sax.SAXException se) {
System.out.println("Error parsing input file:" + se.getMessage());
System.exit(-1);
}
// 将解析出的地址数据打印出来
book.print();
}
private static void addRules(Digester d) {
// 当遇到<person>时,创建类Person的一个实例,并将其压入栈顶
d.addObjectCreate("address-book/person", Person.class);
// 将<person>标签的属性(attribute)与栈顶Person类对象的属性(property)设置方法根据各自的名字进行映射,(例如,将标签属性id与属性设置方法setId进行映射,将标签属性category与属性设置方法setCategory进行映射),然后将属性的值作参数传递给执行相应的方法。
// 如果某标签属性没法通过名字找到相应的属性设置方法,则此标签属性被忽略(如example.xml中第一个<person>的try属性)。
d.addSetProperties("address-book/person");
// 调用第二栈顶对象(AddressBook实例)的addPerson方法,以栈对象(Person实例)的对象为参数
d.addSetNext("address-book/person", "addPerson");
// 当遇到<person>的子元素<name>时,调用栈顶对象(Person实例)的setName方法。
// 此处addCallMethod方法的第一参数是规则,第二个参数是方法的名字,第三个是参数的数量(为0时,表示只有一个参数,且参数的值是元素的内容)
d.addCallMethod("address-book/person/name", "setName", 0);
// 当遇到<person>的子元素<email>时,调用栈顶对象(Person实例)的addEmail方法,addEmail方法有两个参数,取值分别来自<email>的属性type的值和<email>本身的内容。
// 此处addCallParam方法的第一参数是规则,第二个参数是指明被调用方法(addEmail)参数的序号,第三个是参数为字符串时指属性的名字)
d.addCallMethod("address-book/person/email", "addEmail", 2);
d.addCallParam("address-book/person/email", 0, "type");
d.addCallParam("address-book/person/email", 1);
}
private static void usage() {
System.out.println("Usage: java Example1 example.xml");
}
}
运行结果如下(运行时可能需要xml-crimson,一个源sun的XML解析器,可到http://xml.apache.org/crimson/下载)
Person #1
category=acquaintance
name=Gonzo
email (type business) : gonzo@muppets.com
Person #2
category=rolemodel
name=Kermit
email (type business) : kermit@muppets.com
email (type home) : kermie@acme.com
Digester学习笔记(二)转载的更多相关文章
- Digester学习笔记(一)转载
本博文系转载,作者原文已经无法找到,感谢原作者的辛苦整理 Digester学习笔记(一) 在windows下开发程序,用M$提供的接口处理.ini文件或管理注册表的键值是非常方便的.在java平台上开 ...
- Digester学习笔记(三)转载
总觉得,Digester不仅仅能作配置文件解析,而且可以作得更多. 配置属性 Digester用来解析应用系统的配置文件,其本身也有很可配置的属性. 属性 描述 classLoader 指定类装载器( ...
- java之jvm学习笔记二(类装载器的体系结构)
java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...
- NumPy学习笔记 二
NumPy学习笔记 二 <NumPy学习笔记>系列将记录学习NumPy过程中的动手笔记,前期的参考书是<Python数据分析基础教程 NumPy学习指南>第二版.<数学分 ...
- 学习笔记(二)--->《Java 8编程官方参考教程(第9版).pdf》:第七章到九章学习笔记
注:本文声明事项. 本博文整理者:刘军 本博文出自于: <Java8 编程官方参考教程>一书 声明:1:转载请标注出处.本文不得作为商业活动.若有违本之,则本人不负法律责任.违法者自负一切 ...
- WPF的Binding学习笔记(二)
原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...
- AJax 学习笔记二(onreadystatechange的作用)
AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...
- [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计
源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...
- JMX学习笔记(二)-Notification
Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...
随机推荐
- mysql 更改密码
Mac 安装mysql时会生成一个默认密码: 这个可以在通知中找到,如果你需要更改密码则继续看下面, 今天给mac安装了MySQL,安装过程非常的顺利,但是在用一个可视化工具进行连接时,需要输入密码, ...
- PHP 连接打开新网页带参数
PHP 连接打开新网页带参数 detail.php?ID=<?PHP echo $row['ID'];?> aa.php?ID=123 取ID参数 $aid=$_GET['ID']; 网页 ...
- Spring boot + Gradle + Eclipse打war包发布总结
首先感谢两位博主的分享 http://lib.csdn.net/article/git/55444?knId=767 https://my.oschina.net/alexnine/blog/5406 ...
- iOS学习之第二个View使用UITabBarViewController
前面有一篇博文iOS学习之Tab Bar的使用和视图切换 这是在AppDelegate里使用Tabbar,这样的程序打开就是TabbarView了,有时候我们需要给程序做一些帮助页面,或者登录页面,之 ...
- 改bug的乐趣
一直以来,我都不喜欢改bug,不管是自己的,还是别人的.因为我不相信自己的代码会出现问题,一旦出现问题我就会觉得很难堪,因为我觉得我的代码没什么问题.然后我就不知道该怎么来解决这些问题. 最近这一两次 ...
- debian:jessie 安转percona mysql
dpkg -r percona-server-server-5.6 dpkg -r percona-server-client-5.6 dpkg -r libperconaserverclient18 ...
- Python基础:面向对象基础 (一) 类及其属性和魔法方法
定义类,添加和获取对象属性 # 定义类 格式如下 # class 类名: # 方法列表 # 新式类定义形式 # info 是一个实例方法,第一个参数一般是self,表示实例对象本身 class Her ...
- markdown转HTML,目录生成
1.首先,准备好已经编辑好的markdown文件放到指定目录下. 2.下载node.js,下载地址:https://nodejs.org/en/download/ 3.下载好node.js文件后,配置 ...
- NSArray 快速求和、平均值、最大值、最小值
在iOS开发中我们经常遇到一个需求,求一个数组的所有元素的和,最大值,最小值或者平均值,有的开发者可能第一想到的是for循环遍历求解,其实苹果提供了更简便的方式.如下: NSArray *arr = ...
- 虚拟机安装centos发现inet为127.0.0.1,导致Xshell连接不上
问题如标题所示: 设置网卡开机自动启动: 实质linux是看一个网卡文件的配置,就是/etc/sysconfig/network-scripts/ifcfg-eth0 (这个文件名看你网卡名称而异,具 ...