用Digester实现xml转换成bean

    项目中要用到解析配置文件的功能,google了一下,发现基本都是说用Digester的,正好工程中有这个jar包,所以可以用,研究了一下。Digester原来是struts1.x下面的jar,但由于解析xml到bean是个如此常用的功能,于是就分出来了,成为apache一个单独的项目了,它用纯java实现。试了一下,解析xml还是挺方便的。下面是我改写了官网提供的一个例子,基本覆盖常用的功能。

 

example.xml:

 <address-book> <person id="1" category="acquaintance" birth="1978-10-16"> <name>Gonzo</name> <email type="business">[email protected]</email> <address> <type>home</type> <street>123 Maine Ave.</street> <city>Las Vegas</city> <state>NV</state> <zip>01234</zip> <country>USA</country> </address> <address> <type>business</type> <street>234 Maple Dr.</street> <city>Los Angeles</city> <state>CA</state> <zip>98765</zip> <country>USA</country> </address> <hobbie> <item>sprots</item> <item>pets</item> </hobbie> </person> <person id="2" category="rolemodel" birth="1958-2-3"> <name>Kermit</name> <email type="business">[email protected]</email> <email type="home">[email protected]</email> <address> <type>business</type> <street>987 Brown Rd</street> <city>Las Cruces</city> <state>NM</state> <zip>75321</zip> <country>USA</country> </address> <hobbie> <item>driving</item> <item>music</item> </hobbie> </person> </address-book>

 

beans:

package addressbook; import java.util.LinkedList; public class AddressBook { LinkedList people = new LinkedList(); public void addPerson(Person p) { people.addLast(p); } } package addressbook; import java.util.ArrayList; import java.util.List; public class Hobbie { private List<String> items = new ArrayList<String>(); public void addItem(String item) { items.add(item); } public List<String> getItems() { return items; } }

 

 package addressbook; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; /** * See Main.java. */ public class Person { private int id; private String category; private String name; private HashMap<String, String> emails = new HashMap<String, String>(); private List<Address> addresses = new ArrayList<Address>(); private Hobbie hobbie; private String birthDay; /** * A unique id for this person. Note that the Digester automatically * converts the id to an integer. */ public void setId(int id) { this.id = id; } public void setCategory(String category) { this.category = category; } public void setName(String name) { this.name = name; } /** * we assume only one email of each type... */ public void addEmail(String type, String address) { emails.put(type, address); } public void addAddress(Address addr) { addresses.add(addr); } public void setHobbie(Hobbie hobbie) { this.hobbie = hobbie; } public HashMap<String, String> getEmails() { return emails; } public void setEmails(HashMap<String, String> emails) { this.emails = emails; } public List<Address> getAddresses() { return addresses; } public void setAddresses(List<Address> addresses) { this.addresses = addresses; } public Hobbie getHobbie() { return hobbie; } public void setBirthDay(String birthDay) { this.birthDay = birthDay; } }

 

 

 

package addressbook; import java.util.HashMap; import java.util.Iterator; public class Address { private String type; private String street; private String city; private String state; private String zip; private String country; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } }

 

 

 

测试类:

package addressbook; import org.apache.commons.digester.Digester; public class Main { public static void main(String[] args) throws Exception { Digester d = new Digester(); AddressBook book = new AddressBook(); d.push(book); addRules(d); d.parse(Main.class.getResource("/addressbook/example.xml")); System.out.println("bye bye"); } private static void addRules(Digester d) { d.addObjectCreate("address-book/person", Person.class); //建立Person对象 d.addSetProperties("address-book/person"); //在AddressBook上添加这个person d.addSetNext("address-book/person", "addPerson"); //读取name d.addCallMethod("address-book/person/name", "setName", 0); // d.addBeanPropertySetter("address-book/person/name"); //添加email d.addCallMethod("address-book/person/email", "addEmail", 2); d.addCallParam("address-book/person/email", 0, "type"); d.addCallParam("address-book/person/email", 1); //添加address对象 d.addObjectCreate("address-book/person/address", Address.class); d.addSetNext("address-book/person/address", "addAddress"); d.addSetNestedProperties("address-book/person/address"); //添加Hobbie对象 d.addObjectCreate("address-book/person/hobbie", Hobbie.class); d.addSetNext("address-book/person/hobbie", "setHobbie"); d.addCallMethod("address-book/person/hobbie/item", "addItem", 0); } }

 

 

简单说明一下,

1)当创建bean中的bean属性时,如AddressBook的Person对象,总是需要两步:

addObjectCreate

addSetNext

前者是告诉系统下面的元素会映射成一个对象,后者告诉系统用当前父对象的哪个方法将这个新的子对象添加进来,不能以addCallMethod代替,如果用了,会发现多个元素时,只有一个被添加了进去,原因我也不知道,文档讲得也不清楚.

 

2)读取attribute

   两种办法,一种是addSetProperties(),它会用xml中的attribute来设置bean上同名的property,如果两者名字不同怎么办,如例中xml里是birth,而bean中叫birthDay,用第二种办法addSetProperties("address-book/person","birth","birthDay");

 

3)将元素文本设置给bean的property

   我一般比较喜欢用addBeanPropertySetter,用addCallMethod也可以,不过要指定参数的个数,如果只有一个参数,那么个数用0表示,a little weird。

 

   另外,addSetNestedProperties这个方法可以将一组元素按钮元素名设置给bean的property,如:

<address> <type>business</type> <street>234 Maple Dr.</street> <city>Los Angeles</city> <state>CA</state> <zip>98765</zip> <country>USA</country> </address>

 

 用addSetNestedProperties("address-book/person/address"),它会把这些子元素都作为property设置给address。

 

 如果想给bean设置一个常量的属性,addCallMethod之后用addObjectParam即可。Digester一点儿也难,多动手练习就会明白。

 

 是不是很简单?了解了原理,当xml结构变化时,可以简单地修改下代码就同步了,另外有种办法貌似是用xmlbeans,用annotation实现的,在一个项目中见过,不过没研究过。

 

官方例子:

http://svn.apache.org/viewvc/commons/proper/digester/trunk/src/examples/

 

需要的其它jar包,commons-logging,BeanUtils

如果想使用日志,定义个commons-logging.properties文件,附上以下内容:

 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

你可能感兴趣的:(exception,bean,xml,String,Class,email)