以下例子示例了如何使用castor转换xml到对象的常见问题配置。
1. 定义要转换到的bean
package test.person;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
public class PersonBean {
private String name;
private String email;
private int age;
private String hobby;
private boolean mailPrivate;
private String dummy;
public String nation;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public boolean isMailPrivate() {
return mailPrivate;
}
public void setMailPrivate(boolean mailPrivate) {
this.mailPrivate = mailPrivate;
}
public String getDummy() {
return dummy;
}
public void setDummy(String dummy) {
this.dummy = dummy;
}
public String toString() {
return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString();
}
}
2. 定义数据xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<Person>
<Name>lee</Name>
<Age>30</Age>
<Address>
<Mails>
<Email private="true">[email protected]</Email>
</Mails>
</Address>
<Nation>Chinese</Nation>
</Person>
对应关系:
1) Name标签对应PersonBean.name
2) Age标签对应PersonBean.age
3) Email标签的内容对应PersonBean.email
4) Email标签的属性private对应PersonBean.mailPrivate
5) PersonBean.hobby不需要从数据xml中获得。
6) PersonBean.dummy期望的对应元素是Person/xxx,但是数据xml文件中并不存在。
3.定义映射对象
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN" "http://castor.org/mapping.dtd">
<mapping>
<class name="test.person.PersonBean">
<map-to xml="Person"/>
<field name="Name" type="java.lang.String">
<bind-xml name="Name" node="element"/>
</field>
<field name="Age" type="integer">
<bind-xml name="Age" node="element"/>
</field>
<field name="Email" type="java.lang.String">
<bind-xml name="Email" location="Address/Mails" node="element"/>
</field>
<field name="MailPrivate" type="boolean">
<bind-xml name="private" location="Address/Mails/Email" node="attribute"/>
</field>
<field name="Dummy" type="java.lang.String">
<bind-xml name="xxx" node="element"/>
</field>
<field name="nation" type="java.lang.String" direct="true">
<bind-xml name="Nation" node="element"/>
</field>
</class>
</mapping>
要点:
1)map-to标签表示从xml的哪个节点开始映射对象。
2) field元素中属性name的值,推荐使用setXXX属性去掉set后的字符串。castor是按照name属性的值来反射生成setXXX方法。如果setXXX方法名称是按照JavaBean约定的命名规则定义的话,name属性值用小写字母开头也可。
3) castor默认对于含有子节电的每个xml元素都认为是一个对象,要想不通过建立对象直接关联值的话,使用location属相指定XPath的相对路径
4)如果xml中不存在某个期望的元素,castor会忽略映射。
5)如果JavaBean中的对象没有set方法,可以使用direct="true"来直接赋值,前提是JavaBean的属性必须定义成public
6) location属性不作为bind-xml的标志符,意味着如果在class元素内有多个<bind-xml>节点含有相同name属性值的话,castor将会出错,并抛出如下异常
element xxx occurs more than once
参见
http://jira.codehaus.org/browse/CASTOR-690
4. 测试代码
package test.person;
import java.io.FileReader;
import java.io.Reader;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.xml.Unmarshaller;
import test.ShareClass;
public class PersonBeanTest {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
test1();
}
public static void test1() throws Exception{
Mapping mapping = new Mapping();
String mappingFile = PersonBeanTest.class.getClassLoader().getResource("test/person/person-mapping.xml").getFile();
mapping.loadMapping(mappingFile);
Unmarshaller unmarshaller = new Unmarshaller(mapping);
unmarshaller.setIgnoreExtraElements(true);
unmarshaller.setIgnoreExtraAttributes(true);
String dataFile = PersonBeanTest.class.getClassLoader().getResource("test/person/person.xml").getFile();
Reader reader = new FileReader(dataFile);
PersonBean pb = (PersonBean)unmarshaller.unmarshal(reader);
System.out.println(pb);
}
}
输出结果
test.person.PersonBean@15e9756[
name=lee
[email protected]
age=30
hobby=<null>
mailPrivate=true
dummy=<null>
nation=Chinese
]
注意:
1)如果JavaBean中含有在xml中没有对应元素,如果不设置setIgnoreExtraElements和setIgnoreExtraAttributes为true的话,castor将会抛出异常。
2) 在多线程环境中,应每次new一个Unmarshaller对象实例保证线程安全,否则可以使用Unmarshaller的静态方法。
3)
5.其他
对象嵌套的映射文件写法
5.1 可以将所有对象都放到<mapping>元素下
<mapping>
<class name="test.TestClass1">
......
</class>
<class name="test.TestClass2">
......
</class>
......
</mapping>
5.2 可以导入外部文件
<mapping>
<include href="mapping1.xml"/>
<include href="mapping2.xml"/>
......
<class name="test.TestClass">
......
</class>
</mapping>
更多参见castor官方文档
http://www.castor.org/reference/html-single/index.html