Digester学习笔记(二)为便于理解,将笔记的内容结构作了一些调整。
对象栈对digester技术最普通的应用,是用来动态创建一个由Java对象构成的树结构,各对象的属性以及对象间的关系,基于XML文档的内容来设置(XML文档就是一棵树)。为实现这种应用,Digester提供了一个对象栈,以供在相关的模板识别后被激活的处理规则操作。此栈的基本操作包括:
用栈的原因,就是当识别出一个XML元素的“开始”时,将相关对象生成并压入栈顶,这个对象在处理该元素的子元素的过程中一直在栈中,当所有子元素都处理完后,解析器遇到这个元素的“结束”时,则弹出此对象,并进行相关的处理。 如何描述对象间的关系呢?将栈顶的对象做为一个参数,传递给第二栈顶(即先于栈顶对象入栈的那个对象,在栈顶对象的下面)的一个方法,就可以简单地建立起一种“父子关系”,从而可以简单地建立起1:1的关系(第二栈顶对象与栈顶对象之间)和1:N的关系(第二栈顶对象不动,N次压栈顶弹栈顶对象). 如果取得生成的第一个对象呢?可以让parse()方法返回,或者在调用parse()方法前,先行压入一个对象,在parse()方法结束后弹出这个对象,则其子对象即为我们想要的第一个对象。 日志(logging)日志是一个调试Digester规则集的非常重要的工具,它可以记录非常丰富的信息,因它在使用Digester之前有必要了解日志是如何工作的。 Digester使用Jakarta Commons Logging,这个模块并不是具体的日志实现,而只是一个可设置的接口。可以设置它将各种日志信息传递它自身带的基本记录器,或者传递给其它的更复杂的日志工具。具体请参考commons logging的文档,或Jakarta Commons Logging学习笔记 Digester主要使用两个记录器:
假定用commons logging自带的基本日志工具,并以DEBUG级别记录Digester调试信息以及INFO级别记录SAX事件信息,则对logging的配置文件设置如下: org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog org.apache.commons.logging.simplelog.log.org.apache.commons.digester.Digester=debug org.apache.commons.logging.simplelog.log.org.apache.commons.digester.Digester.sax=info
Digester包中的例子***********Example.xml**********
运行结果如下(运行时可能需要xml-crimson,一个源sun的XML解析器,可到http://xml./crimson/下载)
<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(); ) { // 调用第二栈顶对象(AddressBook实例)的addPerson方法,以栈对象(Person实例)的对象为参数 private static void usage() { Address book has 2 entries
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 |
|
来自: shaobin0604@1... > 《Java》