一、 简介
Castor XML是一种XML数据绑定框架。
XML的另外两种主要API:DOM和SAX(Document Object Model和Simple API for XML),主要是从结构的角度去处理XML文件,而Castor XML是以对象的模式去处理XML文档中的数据
大多数情况下,转换框架通过ClassDescriptor和FieldDescriptor来描述转换时所需要的信息。
二、 转换框架
转换框架中最主要的两个类是:org.exolab.castor.xml.Marshaller和org.exolab.castor.xml.Unmarshaller
marshal: Marshaller.marshal(obj,writer);
unmarshal: Unmarshaller.unmarshal(Person.class,reader);
上面的这种转换方式,只适合于按照默认方式进行转化,如果要使用映射文件,需要采用以下方式。
marshal:
Mapping mapping = new Mapping(); mapping.loadMapping(“mapping.xml”); Marshaller marshaller = new Marshaller(writer); marshaller.setMapping(mapping); marshaller.marshal(obj);
Marshaller的5个marshal方法中,只有marshal(Object obj)这个方法不是静态的,其他的四个都是静态的marshal(obj,writer), marshal(obj,handler), marshal(obj,node)
unmarshal:
Mapping mapping = new Mapping(); mapping .loadMapping(“mapping.xml”); Unmarshaller unm = new Unmarshaller(“Person.class”);//使用Person.class作为构造Unmarshaller的参数 unm.setMapping(mapping); Person person = (Person)unm.unmarshal(reader);
Unmarshaller中,object可以从reader中转换而来,也可以从source、node转换而来,静态方法均是两个参数,非静态方法都是一个来源作为参数。
三、 使用存在的Class和对象
Castor几乎可以将任何对象和XML进行转换。当指定class的描述文件不存在时,转换框架使用默认的reflection机制来获得对象的信息。
转化对象存在的主要约束是:
这些class必须有一个public而且default的构造函数;必须有adequate get/set方法。
四、 类描述符(ClassDescriptor)
org.exolab.castor.xml.XMLClassDescriptor
类描述符提供转换时所需的必要信息。ClassDescriptor不仅可以用于Castor XML,还可以用于Castor JDO
类描述符包括一组字段描述符(FieldDescriptor)
类描述符通常情况下有四种创建方式,两种在编译时(效率较高),两种在运行时(较为方便)
编译时描述符:
1. 让需要被describe的类实现org.exolab.castor.xml.XMLClassDescriptor接口
2. 使用Source Code Generator创建合适的descriptor
运行时描述符:
3. 默认,使用Castor的introspect机制
4. 提供mapping文件,或者默认和配置文件并用
使用”default introspection”机制必须为每一个要转换的field配备对应的get/set方法;
如果没有get/set方法,但是是public的field,也可以以direct field access的方式被转换;
但是如果一个类中为有的成员定义了get/set方法,即使其他成员是public的,也不会被转换;
自动内省机制是自动触发的。可以通过castor.properties文件控制自动转换的特性,比如改变名称转换、基本型别是转换为attribute还是element等。
Mapping文件也可以用来描述要被转换的类。mapping的装载发生在marshal和unmarshal之前(org.exolab.castor.mapping.Mapping)
---------------------------实例--------------------------------------------------
1. Castor是什么
Castor是一种将Java对象和XML自动绑定的开源软件.它可以在Java对象,XML文本,SQL数据表以及LDAP目录之间绑定.
Castor XML is an XML databinding framework. Unlike the two main XML APIs, DOM (Document Object Model) and SAX (Simple API for XML) which deal with the structure of an XML document, Castor enables one to deal with the data defined in an XML document through an object model which represents that data.
Castor能把Java对象和XML文档进行转换,使用户从复杂的XML解析中解放出来,更关注于数据而不是文档。
Castor 网址: http://www.castor.org/
2 Castor使用
Java对象指的是具有setX和getX方法的JavaBean,
将Castor用于JavaBean具体使用方法如下
缺省用法:缺省用法指的是没有使用映射格式描述文件时的用法
标准用法:标准用法指的是使用映射格式描述文件时的用法
实际上,Castor 不仅仅能用于本文所述的类 JavaBean 类。它也可以访问带有公共成员变量的简单数据对象类的数据。比如,稍微改动前述的 Test 类,您就可以对航班数据使用如下的定义,并最终得到同样的 XML 格式:
public class FlightData { public String carrier; public int number; public String departure; public String arrival; }
为了使 Castor 正常工作,一个类必须全部采用这种方式或那种方式。如果类定义了 任何 getX 或 setX 方法,Castor 就将其视作 bean,并在编组和解组时只使用这些方法
3 缺省用法下xml的格式
<?xml version=1.0 encoding=UTF-8?> <arrival-time>8:42a</arrival-time> <departure-time>6:23</departure-time> <carrier>AR</carrier>
也就是说
对于具有基本类型值的属性创建元素的一个属性(本例中只有 number 属性通过 getNumber() 方法公开为 int 值)。对于每个具有对象类型值的属性创建根元素的一个子元素(本例中的所有其他属性,因为它们是字符串)
4 标准用法下xml格式
<?xml version="1.0"?> <flight carrier="AR" depart="6:23a" arrive="8:42a" number="426"/>
这一般是我们期望的,只所以生成我们所期望的格式,是因为我们使用了映射格式描述文件。它也是XML文件:
<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.exolab.org/mapping.dtd"> <mapping> <description>Basic mapping example</description> <class name="castortest.FlightBean" auto-complete="true"> <map-to xml="flight"/> <field name="carrier"> <bind-xml name="carrier" node="attribute"/> </field> <field name="departureTime"> <bind-xml name="depart" node="attribute"/> </field> <field name="arrivalTime"> <bind-xml name="arrive" node="attribute"/> </field> </class> </mapping>
mapping.xml各个配置参数说明:
<?xml version="1.0"?> <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.exolab.org/mapping.dtd"> <mapping> <description>A mapping file for our Address Book application</description> <class name="com.dxz.castor.Person"> <map-to xml="person"/> <field name="name" type="string"> <bind-xml name="name" node="attribute" /> </field> <field name="address" type="string" > <bind-xml name="address" node="element" /> </field> <field name="ssn" type="string" > <bind-xml name="ssn" node="element" /> </field> <field name="email" type="string"> <bind-xml name="email" node="element" /> </field> <field name="homePhone" type="string"> <bind-xml name="home-phone" node="element" /> </field> <field name="workPhone" type="string"> <bind-xml name="work-phone" node="element" /> </field> </class> <class name="com.dxz.castor.Persons"> <map-to xml="persons"/> <field name="persons" collection="arraylist" type="com.dxz.castor.Person"> <bind-xml name="persons" auto-naming="deriveByClass"/> </field> </class> <class name="com.dxz.castor.Addressbook"> <map-to xml="addressbook"/> <field name="name" type="string"> <bind-xml name="name" node="attribute" /> </field> <field name="persons"/> </class> </mapping>
mapping:看看这个xml文档的根元素是mapping,在mapping中可以配置class。也就是我们要转换的JavaObject的配置描述了;
class:class元素的name属性就是配置的JavaObject的classpath路径(包含class的包路径)了;
class元素的auto-complate属性:
如果这个属性的值为ture:那么编组后的xml,castor会自动给没有在mapping配置文件进行配置的属性自动编组(转换)到xml中;
如果为false,那么只有在mapping配置文件中出现的属性,将出现在编组后的xml中,没有配置的将没有;
map-to:map-to就是当前class编组后的xml文档的节点元素名称;
field:field就是描述JavaObject中的属性,name是Java对象的属性名称,type是类型。关于配置的type类型也有规定,你可以参考:http://www.castor.org/xml-mapping.html的field配置讲解。而field还有其他的属性配置,如get-method应该是getter方法、set-method应该是setter的方法、has-mehtod应该是hashCode方法,有时候我们不一定要提高getter、setter方法,我们需要用自己的方法名称来代替setter、getter。如果当前field配置的是集合类型,那么你需要给field元素配置collection属性。
bind-xml:bind-xml就是绑定(编组)成xml后的xml内容的描述,name就是编组后xml的节点元素名称,node有2个值,分别是 attribute、element。attribute是属性,它会在节点元素的属性中显示,例如:<account id=”2”></account>而element则是单独的一个元素,例如:<account><id>2</id></account>就这个样子的。
include:mapping.xml还可以有其他标签,如:
<include href="other_mapping_file.xml"/>导入外部xml文件,可以分多个配置。
配置举例:
List与XML mapping配置:
<class name="com.dxz.castor.Persons"> <map-to xml="persons"/> <field name="persons" collection="arraylist" type="com.dxz.castor.Person"> <bind-xml name="persons" auto-naming="deriveByClass"/> </field> </class>
MAP与XML mapping配置:
<class name="com.hoo.entity.MapBean"> <field name="map" collection="map"> <bind-xml name="map"> <class name="org.exolab.castor.mapping.MapItem"> <field name="key" type="java.lang.String"> <bind-xml name="key" node="attribute" /> </field> <field name="value" type="com.hoo.entity.Account"> <bind-xml name="value" auto-naming="deriveByClass"/> </field> </class> </bind-xml> </field> </class>
===========================================
Castor绑定xml使用技巧
1 castor.properties 缩进问题和命名规范
通过修改jar包下org\exolab\castor\castor.properties文件,使得
org.exolab.castor.indent=true
org.exolab.castor.xml.naming=mixed
加上上面的第一个属性就能使产生的xml有缩进,格式比较好看(调试的时候可以用用,正式环境还是去掉比较好)
第二属性设置后,生成的xml的元素名称就可以达到基本符合java的命名规范。
2 使用<class name="com.acme.Foo" auto-complete="true"/>
auto-complete来化繁为简(不用写具体的绑定配置),采用castor默认的绑定配置方式,也即是
对于具有基本类型值的属性创建元素的一个属性(例如number 属性通过 getNumber() 方法公开为 int 值;)对于每个具有对象类型值的属性创建根元素的一个子元素。
3 使用代码获取castor的各个properties
从castor1.1开始,可以使用getProperty(String)和setProperty(String,String)编程来设置或者读取相应的属性值,可以使用这两个方法的类是org.exolab.castor.xml.Unmarshaller,org.exolab.castor.xml.Marshaller,org.exolab.castor.xml.XMLContext。
前两个类的setter方法只对相应实例的设置有效,毕竟Unmarshaller和Marshaller实例是通过createUnmarshaller()和createMarshaller()方法创建得来的。而XMLContext的setProperty()方法会修改全局的配置参数
4
class.getClassLoader().getResources
this.getClass().getClassLoader().getResource("template");
首先,调用对象的getClass()方法是获得对象当前的类类型,这部分数据存在方法区中,而后在类类型上调用getClassLoader()方法是得到当前类型的类加载器,我们知道在Java中所有的类都是通过加载器加载到虚拟机中的,而且类加载器之间存在父子关系,就是子知道父,父不知道子,这样不同的子加载的类型之间是无法访问的(虽然它们都被放在方法区中),所以在这里通过当前类的加载器来加载资源也就是保证是和类类型同一个加载器加载的。
==============================
Castor进行XML数据绑定
Castor是一个java object的OR Mapping工具,可以将java objects保存于database、xml文件和LDAP数据库中(目前版本好像LDAP支持有问题)。下面简单介绍一下怎样用Castor来操纵XML文件
一、最简单的XML文件的操纵
1. 1 读取XML文件
有一个xml文件如下,表示了一个人的信息
person.xml
<?xml version="1.0"?> <person> <name>Bob Harris</name> <ssn>222-222-2222</ssn> <address>123 Foo Street</address> <work-phone>(123) 123-1234</work-phone> <home-phone>(123) 123-1234</home-phone> <email>[email protected]</email> </person>
对应的java文件
package com.dxz.castor; import java.io.*; public class Person { private String name; private String address; private String ssn; private String email; private String homePhone; private String workPhone; // -- allows us to create a Person via the constructor public Person(String name, String address, String ssn, String email, String homePhone, String workPhone) { this.name = name; this.address = address; this.ssn = ssn; this.email = email; this.homePhone = homePhone; this.workPhone = workPhone; } // -- used by the data-binding framework public Person() { } // -- accessors public String getName() { return name; } public String getAddress() { return address; } public String getSsn() { return ssn; } public String getEmail() { return email; } public String getHomePhone() { return homePhone; } public String getWorkPhone() { return workPhone; } // -- mutators public void setName(String name) { this.name = name; } public void setAddress(String address) { this.address = address; } public void setSsn(String ssn) { this.ssn = ssn; } public void setEmail(String email) { this.email = email; } public void setHomePhone(String homePhone) { this.homePhone = homePhone; } public void setWorkPhone(String workPhone) { this.workPhone = workPhone; } }
这是一个读取person.xml文件的例子
package com.dxz.castor; import org.exolab.castor.xml.*; import java.io.FileReader; public class ReadPerson { public static void main(String args[]) { try { Person person = (Person) Unmarshaller.unmarshal(Person.class, new FileReader("person.xml")); System.out.println("Person Attributes"); System.out.println("-----------------"); System.out.println("Name: " + person.getName()); System.out.println("Address: " + person.getAddress()); System.out.println("SSN: " + person.getSsn()); System.out.println("Email: " + person.getEmail()); System.out.println("Home Phone: " + person.getHomePhone()); System.out.println("Work Phone: " + person.getWorkPhone()); } catch (Exception e) { System.out.println(e); } } }
结果:
Person Attributes ----------------- Name: Bob Harris Address: 123 Foo Street SSN: 222-222-2222 Email: [email protected] Home Phone: (123) 123-1234 Work Phone: (123) 123-1234
传统上,如果需要操纵XML文件,需要用SAX或者DOM来处理,比较繁琐,有了Castor提供的marshalling and unmarshalling功能,就可以方便的在xml和java object之间方便的映射了。
2. 2 生成XML文件
下面是生成XML文件的例子:
package com.dxz.castor; import org.exolab.castor.xml.*; import java.io.FileWriter; public class CreatePerson { public static void main(String args[]) { try { // -- create a person to work with Person person = new Person("Bob Harris", "123 Foo Street", "222-222-2222", "[email protected]", "(123) 123-1234", "(123) 123-1234"); // -- marshal the person object out as a <person> FileWriter file = new FileWriter("D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\bob_person.xml"); Marshaller.marshal(person, file); file.close(); } catch (Exception e) { System.out.println(e); } } }
这是上面的CreatePerson生成的xml文件
bob_person.xml
<?xml version="1.0" encoding="UTF-8"?> <person> <ssn>222-222-2222</ssn> <address>123 Foo Street</address> <work-phone>(123) 123-1234</work-phone> <name>Bob Harris</name> <home-phone>(123) 123-1234</home-phone> <email>[email protected]</email> </person>
3. 3 修改现有的XML文件
修改现有的XML文件也很简单
package com.dxz.castor; import org.exolab.castor.xml.*; import java.io.FileWriter; import java.io.FileReader; public class ModifyPerson { public static void main(String args[]) { try { // -- read in the person Person person = (Person) Unmarshaller.unmarshal(Person.class, new FileReader("D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\person.xml")); // -- change the name person.setName("David Beckham"); person.setEmail("[email protected]"); // -- marshal the changed person back to disk FileWriter file = new FileWriter("D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\person.xml"); Marshaller.marshal(person, file); file.close(); } catch (Exception e) { System.out.println(e); } } }
二、复杂XML文件的操纵
这个例子演示了如果操纵复杂的xml文件
文件addressbook.xml如下
<?xml version="1.0"?> <addressbook name="Manchester United Address Book"> <person name="Roy Keane"> <address>23 Whistlestop Ave</address> <ssn>111-222-3333</ssn> <email>[email protected]</email> <home-phone>720.111.2222</home-phone> <work-phone>111.222.3333</work-phone> </person> <person name="Juan Sebastian Veron"> <address>123 Foobar Lane</address> <ssn>222-333-444</ssn> <email>[email protected]</email> <home-phone>720.111.2222</home-phone> <work-phone>111.222.3333</work-phone> </person> <person name ="Bob Harris"> <ssn>222-222-2222</ssn> <address>123 Foo Street</address> <work-phone>(123) 123-1234</work-phone> <home-phone>(123) 123-1234</home-phone> <email>[email protected]</email> </person> </addressbook>
可以看到,addressbook包含多条记录,每条记录是一个通讯录。为了对应复杂的xml文件,需要一个mapping.xml文件,来说明xml文件的项目和java object的对应关系.
下面的addressbook-mapping.xml文件:
<?xml version="1.0"?> <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.exolab.org/mapping.dtd"> <mapping> <description>A mapping file for our Address Book application</description> <class name="com.dxz.castor.Person"> <map-to xml="person"/> <field name="name" type="string"> <bind-xml name="name" node="attribute" /> </field> <field name="address" type="string" > <bind-xml name="address" node="element" /> </field> <field name="ssn" type="string" > <bind-xml name="ssn" node="element" /> </field> <field name="email" type="string"> <bind-xml name="email" node="element" /> </field> <field name="homePhone" type="string"> <bind-xml name="home-phone" node="element" /> </field> <field name="workPhone" type="string"> <bind-xml name="work-phone" node="element" /> </field> </class> <class name="com.dxz.castor.Addressbook"> <map-to xml="addressbook"/> <field name="name" type="string"> <bind-xml name="name" node="attribute" /> </field> <field name="persons" collection="arraylist" type="com.dxz.castor.Person"> <bind-xml name="persons" auto-naming="deriveByClass"/> </field> </class> </mapping>
这样,就可以一样很方便的使用Castor来操纵这个XML文件了
同样,需要一个java bean对象文件来对应addressbook.xml,下面是Addressbook.java:
package com.dxz.castor; import java.util.List; import java.util.ArrayList; public class Addressbook { private String addressBookName; private List<Person> persons = new ArrayList<Person>(); public Addressbook() { } // -- manipulate the List of Person objects public void addPerson(Person person) { persons.add(person); } public List getPersons() { return persons; } // -- manipulate the name of the address book public String getName() { return addressBookName; } public void setName(String name) { this.addressBookName = name; } }
操作类:
1、查看addressbook的java代码:
package com.dxz.castor; import org.exolab.castor.xml.*; import org.exolab.castor.mapping.*; import java.io.FileReader; import java.util.List; import java.util.Iterator; public class ReadAddressbook { public static void main(String args[]) { try { // -- Load a mapping file Mapping mapping = new Mapping(); mapping.loadMapping("D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\addressbook-mapping.xml"); Unmarshaller un = new Unmarshaller(Addressbook.class); un.setMapping(mapping); // -- Read in the Addressbook using the mapping FileReader in = new FileReader("D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\addressbook.xml"); Addressbook book = (Addressbook) un.unmarshal(in); in.close(); // -- Display the addressbook System.out.println(book.getName()); List persons = book.getPersons(); Iterator iter = persons.iterator(); while (iter.hasNext()) { Person person = (Person) iter.next(); System.out.println("\n" + person.getName()); System.out.println("-----------------------------"); System.out.println("Address = " + person.getAddress()); System.out.println("SSN = " + person.getSsn()); System.out.println("Home Phone = " + person.getHomePhone()); System.out.println("email = " + person.getEmail()); } } catch (Exception e) { System.out.println(e); } } }
2.修改
package com.dxz.castor; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.OutputStreamWriter; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.Unmarshaller; public class ModifyAddressbook { public static void main(String args[]) { try { // -- Load a mapping file Mapping mapping = new Mapping(); mapping.loadMapping("D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\addressbook-mapping.xml"); Unmarshaller un = new Unmarshaller(Addressbook.class); un.setMapping(mapping); // -- Read in the Addressbook using the mapping FileReader in = new FileReader( "D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\addressbook.xml"); Addressbook book = (Addressbook) un.unmarshal(in); in.close(); book.setName("duanxz2"); Person person = new Person(); person.setAddress("shenzhen2"); person.setEmail("[email protected]"); person.setHomePhone("123456"); person.setName("duanxz2"); person.setSsn("ssn2"); person.setWorkPhone("0755-12345678"); book.addPerson(person); // -- marshal the changed person back to disk FileWriter file = new FileWriter( "D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\bob_addressbook.xml"); Marshaller marshaller = new Marshaller(file); marshaller.setMapping(mapping); marshaller.marshal(book); file.close(); } catch (Exception e) { e.printStackTrace(); } } }
上面的修改操作生成的bob_addressbook.xml如下:
<?xml version="1.0" encoding="UTF-8"?> <addressbook name="duanxz2"> <person name="Bob Harris"> <address>123 Foo Street</address> <ssn>222-222-2222</ssn> <email>[email protected]</email> <home-phone>(123) 123-1234</home-phone> <work-phone>(123) 123-1234</work-phone> </person> <person name="duanxz2"> <address>shenzhen2</address> <ssn>ssn2</ssn> <email>[email protected]</email> <home-phone>123456</home-phone> <work-phone>0755-12345678</work-phone> </person> <person name="Juan Sebastian Veron"> <address>123 Foobar Lane</address> <ssn>222-333-444</ssn> <email>[email protected]</email> <home-phone>720.111.2222</home-phone> <work-phone>111.222.3333</work-phone> </person> <person name="Roy Keane"> <address>23 Whistlestop Ave</address> <ssn>111-222-3333</ssn> <email>[email protected]</email> <home-phone>720.111.2222</home-phone> <work-phone>111.222.3333</work-phone> </person> </addressbook>
改进1:让list列表有顺序,需要在每次取出(解组成)javabean时需要排序,及在保存到xml之前,将list排序一次。(xml中顺序保证)。
为了让addresssbook中person排序,需要修改Person类和Addressbook类:
package com.dxz.castor; import java.io.*; import java.util.Comparator; public class Person { public static final Comparator person_COMPARATOR = new PersonComparator(); private String name; private String address; private String ssn; private String email; private String homePhone; private String workPhone; // -- allows us to create a Person via the constructor public Person(String name, String address, String ssn, String email, String homePhone, String workPhone) { this.name = name; this.address = address; this.ssn = ssn; this.email = email; this.homePhone = homePhone; this.workPhone = workPhone; } // -- used by the data-binding framework public Person() { } // -- accessors public String getName() { return name; } public String getAddress() { return address; } public String getSsn() { return ssn; } public String getEmail() { return email; } public String getHomePhone() { return homePhone; } public String getWorkPhone() { return workPhone; } // -- mutators public void setName(String name) { this.name = name; } public void setAddress(String address) { this.address = address; } public void setSsn(String ssn) { this.ssn = ssn; } public void setEmail(String email) { this.email = email; } public void setHomePhone(String homePhone) { this.homePhone = homePhone; } public void setWorkPhone(String workPhone) { this.workPhone = workPhone; } private static class PersonComparator implements Comparator, Serializable { //~ Methods ---------------------------------------------------------------------------------------------------- public int compare(Object o1, Object o2) { if ((o1 instanceof Person) && (o2 instanceof Person)) { String transName1 = ((Person) o1).getName(); String transName2 = ((Person) o2).getName(); return transName1.compareToIgnoreCase(transName2); } return -1; } } }
package com.dxz.castor; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.ArrayList; public class Addressbook { private String addressBookName; private List<Person> persons = new ArrayList<Person>(); public Addressbook() { } // -- manipulate the List of Person objects public void addPerson(Person person) { persons.add(person); Collections.sort(persons,Person.person_COMPARATOR); } public List getPersons() { return persons; } // -- manipulate the name of the address book public String getName() { return addressBookName; } public void setName(String name) { this.addressBookName = name; } }
改进2:将上面xml中的list增加一个父节点persons,方便阅读,如下:
<persons> <person name="Bob Harris"> <address>123 Foo Street</address> <ssn>222-222-2222</ssn> <email>[email protected]</email> <home-phone>(123) 123-1234</home-phone> <work-phone>(123) 123-1234</work-phone> </person> <person name="duanxz2"> <address>shenzhen2</address> <ssn>ssn2</ssn> <email>[email protected]</email> <home-phone>123456</home-phone> <work-phone>0755-12345678</work-phone> </person> </persons>
方法:
addressbook-mapping.xml需要修改::
<?xml version="1.0"?> <!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.exolab.org/mapping.dtd"> <mapping> <description>A mapping file for our Address Book application</description> <class name="com.dxz.castor.Person"> <map-to xml="person"/> <field name="name" type="string"> <bind-xml name="name" node="attribute" /> </field> <field name="address" type="string" > <bind-xml name="address" node="element" /> </field> <field name="ssn" type="string" > <bind-xml name="ssn" node="element" /> </field> <field name="email" type="string"> <bind-xml name="email" node="element" /> </field> <field name="homePhone" type="string"> <bind-xml name="home-phone" node="element" /> </field> <field name="workPhone" type="string"> <bind-xml name="work-phone" node="element" /> </field> </class> <class name="com.dxz.castor.Persons"> <map-to xml="persons"/> <field name="persons" collection="arraylist" type="com.dxz.castor.Person"> <bind-xml name="persons" auto-naming="deriveByClass"/> </field> </class> <class name="com.dxz.castor.Addressbook"> <map-to xml="addressbook"/> <field name="name" type="string"> <bind-xml name="name" node="attribute" /> </field> <field name="persons"/> </class> </mapping>
增加一个Persons类:
/** * */ package com.dxz.castor; import java.util.ArrayList; import java.util.Collections; /** * @author duanxz * */ public class Persons { private ArrayList<Person> persons = new ArrayList<Person>(); public ArrayList<Person> getPersons() { return persons; } public void setPersons(ArrayList<Person> persons) { this.persons = persons; Collections.sort(this.persons, Person.person_COMPARATOR); } public void addPerson(Person person){ this.persons.add(person); } }
Addressbook.java
package com.dxz.castor; public class Addressbook { private String addressBookName; private Persons persons; public String getName() { return addressBookName; } public void setName(String addressBookName) { this.addressBookName = addressBookName; } public Persons getPersons() { return persons; } public void setPersons(Persons persons) { this.persons = persons; } }
ReadAddressbook.java
package com.dxz.castor; import org.exolab.castor.xml.*; import org.exolab.castor.mapping.*; import java.io.FileReader; import java.util.ArrayList; import java.util.Iterator; public class ReadAddressbook { public static void main(String args[]) { try { // -- Load a mapping file Mapping mapping = new Mapping(); mapping.loadMapping("D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\addressbook-mapping.xml"); Unmarshaller un = new Unmarshaller(Addressbook.class); un.setMapping(mapping); // -- Read in the Addressbook using the mapping FileReader in = new FileReader("D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\addressbook2.xml"); Addressbook book = (Addressbook) un.unmarshal(in); in.close(); // -- Display the addressbook System.out.println(book.getName()); Persons persons = book.getPersons(); ArrayList al = persons.getPersons(); Iterator iter = al.iterator(); while (iter.hasNext()) { Person person = (Person) iter.next(); System.out.println("\n" + person.getName()); System.out.println("-----------------------------"); System.out.println("Address = " + person.getAddress()); System.out.println("SSN = " + person.getSsn()); System.out.println("Home Phone = " + person.getHomePhone()); System.out.println("email = " + person.getEmail()); } } catch (Exception e) { e.printStackTrace(); } } }
ModifyAddressbook.java
package com.dxz.castor; import java.io.FileReader; import java.io.FileWriter; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.Unmarshaller; public class ModifyAddressbook { public static void main(String args[]) { try { // -- Load a mapping file Mapping mapping = new Mapping(); mapping.loadMapping("D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\addressbook-mapping.xml"); Unmarshaller un = new Unmarshaller(Addressbook.class); un.setMapping(mapping); // -- Read in the Addressbook using the mapping FileReader in = new FileReader( "D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\addressbook2.xml"); Addressbook book = (Addressbook) un.unmarshal(in); in.close(); book.setName("duanxz2"); Person person = new Person(); person.setAddress("shenzhen2"); person.setEmail("[email protected]"); person.setHomePhone("123456"); person.setName("duanxz2"); person.setSsn("ssn2"); person.setWorkPhone("0755-12345678"); book.getPersons().addPerson(person); // -- marshal the changed person back to disk FileWriter file = new FileWriter( "D:\\work\\workspace\\Base\\src\\com\\dxz\\castor\\bob_addressbook.xml"); Marshaller marshaller = new Marshaller(file); marshaller.setMapping(mapping); marshaller.marshal(book); file.close(); } catch (Exception e) { e.printStackTrace(); } } }
生成的bob_addressbook.xml如下:有背景色的是新修改的。
<?xml version="1.0" encoding="UTF-8"?> <addressbook name="duanxz2"> <persons> <person name="Roy Keane"> <address>23 Whistlestop Ave</address> <ssn>111-222-3333</ssn> <email>[email protected]</email> <home-phone>720.111.2222</home-phone> <work-phone>111.222.3333</work-phone> </person> <person name="Juan Sebastian Veron"> <address>123 Foobar Lane</address> <ssn>222-333-444</ssn> <email>[email protected]</email> <home-phone>720.111.2222</home-phone> <work-phone>111.222.3333</work-phone> </person> <person name="Bob Harris"> <address>123 Foo Street</address> <ssn>222-222-2222</ssn> <email>[email protected]</email> <home-phone>(123) 123-1234</home-phone> <work-phone>(123) 123-1234</work-phone> </person> <person name="duanxz2"> <address>shenzhen2</address> <ssn>ssn2</ssn> <email>[email protected]</email> <home-phone>123456</home-phone> <work-phone>0755-12345678</work-phone> </person> </persons> </addressbook>
我遇到的错误:
Castor 异常Exception解析
1、org.exolab.castor.mapping.MappingException: Could not find the class XXXX
首先查看mapping文件中的类名是否已经包含了包名
change <class name="Person"> to: <class name="MyPackage.Person">
change <field name="persons" type="Person" collection="collection" /> to:
<field name="persons" type="MyPackage.Person" collection="collection" />
2、org.exolab.castor.xml.MarshalException: unable to find FieldDescriptor for 'PersonSurName' in ClassDescriptor of PersonNameType{File: [not available]; line: 9; column: 22}
The message says:
Unmarshaller encounters an element 'PersonSurName' for which no mapping definition is known.
意思是说PersonSurName的映射定义未知,需要好好检查一下PersonSurName映射的field或者class等有无写错
3、xml读取异常Invalid byte 1 of 1-byte UTF-8 sequence
说简单点当你解析别人的xml格式出现这个错误可能就是别人在生成xml时没有保存为utf-8的字符编码格式。
在中文版的window下java的默认的编码为GBK,也就是所虽然我们标识了要将xml保存为utf-8格式但实际上文件是以GBK格式来保存的,所以这也就是为什么能够我们使用GBK、GB2312编码来生成xml文件能正确的被解析,而以UTF-8格式生成的文件不能被xml解析器所解析的原因。