应用 Castor 把 XML 转换成相应的 JavaBean(二)
紧接前一篇 应用 Castor 把 XML 转换成相应的 JavaBean(一),本例稍显复杂一些,也就是要使用到映射文件,更复杂的 JavaBean、XML 数据类型和结构,引入自定的 FieldHandler,还有存在 Namespace 的情形。
关于如何使用 Castor 来把 XML 映射成 JavaBean 请着重阅读这个链接 http://www.castor.org/reference/html/XML%20data%20binding.html 中的内容,里面有说明支持的类型,如何定义自己的类型 Handler 及配置 Handler 的属性,mapping.xml 文件怎么写及各部份的意义;还有 castor.properties 的配置,比其中的 suppressNamespaces 为 true 时可以忽略掉 Namespace,默认为 false.
直接看例子吧:
1. persons.xml,这里放了一个 Namespace,并定义了一个 Address 类型,还使得节点名与 Bean 的属性名不一致:
2. PersonList.java:
3. Person.java:
4. Address.java:
5. AddressHandler.java,自定义的类型处理器,用于在 XML 与 Bean 属性间转换特定的类型:
这个 Handler 可没有 JAXB 相对应的 Adapter 那么好理解,要复杂的多,习惯下吧。
6. mapping.xml,映射文件,应该能看到它所表达的意思:
上面有几点得好好看清楚下:
1) class 节点用 name 指定类型
2) field 节点用 type 指定类型
3) node 属性有是 element 也有对应于 attribute
4) address 的 type 为 string,而不是 cc.unmi.castor.Address,写成后者会报错的。
5) 对于 type 节点有 Namespace 时,写法确实很啰嗦的。不过如果在 castor.properties 的配置 suppressNamespaces 为 true 则可以忽略掉 Namespace。
7. Client.java,最后是客户端调用代码:
执行上面的代码控制台输出结果为:
[Unmi,st1|st2,worker, Fantasia,sz|gd,yuan]
结果正确。
最后还是说要用好下 Castor,请仔细阅读 http://www.castor.org/reference/html/XML%20data%20binding.html。原以为 Castor 的资料比 JAXB 少,现在才知道错了。而且就这样稍加深入的了解了下,发现 Castor 确实够强悍的。
参考:1. http://www.castor.org/xml-mapping.html
2. http://castor.org/spring-xml-intro.html
3. http://www.castor.org/xml-framework.html
4. http://www.castor.org/reference/html/XML%20data%20binding.html 永久链接 https://yanbin.blog/castor-xml-to-javabean-2/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
关于如何使用 Castor 来把 XML 映射成 JavaBean 请着重阅读这个链接 http://www.castor.org/reference/html/XML%20data%20binding.html 中的内容,里面有说明支持的类型,如何定义自己的类型 Handler 及配置 Handler 的属性,mapping.xml 文件怎么写及各部份的意义;还有 castor.properties 的配置,比其中的 suppressNamespaces 为 true 时可以忽略掉 Namespace,默认为 false.
直接看例子吧:
1. persons.xml,这里放了一个 Namespace,并定义了一个 Address 类型,还使得节点名与 Bean 的属性名不一致:
1<?xml version="1.0" encoding="UTF-8"?>
2<Persons xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
3 <Person i:Type="worker">
4 <Name>Unmi</Name>
5 <Address>st1|st2</Address>
6 </Person>
7 <Person i:Type="yuan">
8 <Name>Fantasia</Name>
9 <Address>sz|gd</Address>
10 </Person>
11</Persons>2. PersonList.java:
1package cc.unmi.castor;
2
3import java.util.List;
4
5/**
6 * @author Unmi Qiu
7 * CreateTime: Apr 23, 2011
8 */
9public class PersonList {
10 List<Person> persons;
11
12 public List<Person> getPersons() {
13 return persons;
14 }
15
16 public void setPersons(List<Person> persons) {
17 this.persons = persons;
18 }
19}3. Person.java:
1package cc.unmi.castor;
2
3
4/**
5 * @author Unmi Qiu
6 * CreateTime: Apr 23, 2011
7 */
8public class Person {
9 private String name;
10 private Address address;
11 private String type;
12
13 //中间省去所有的 setter/getter 方法
14
15 public String toString() {
16 return name + "," + address + "," + type;
17 }
18}4. Address.java:
1package cc.unmi.castor;
2
3/**
4 * @author Unmi Qiu
5 * CreateTime: Apr 23, 2011
6 */
7public class Address {
8 private String street1;
9 private String street2;
10
11 //中间省去所有的 setter/getter 方法
12
13 public String toString() {
14 return street1 + "|" + street2;
15 }
16}5. AddressHandler.java,自定义的类型处理器,用于在 XML 与 Bean 属性间转换特定的类型:
1package cc.unmi.castor;
2
3import org.exolab.castor.mapping.FieldHandler;
4import org.exolab.castor.mapping.ValidityException;
5
6/**
7 * Custom Address Handler
8 * @author Unmi Qiu
9 * CreateTime: Apr 23, 2011
10 */
11public class AddressHandler implements FieldHandler {
12
13 public Object getValue(Object object) throws IllegalStateException {
14 Person root = (Person)object;
15 if(root.getAddress() == null){
16 return null;
17 }
18
19 return root.getAddress().getStreet1()+"|" + root.getAddress().getStreet2();
20 }
21
22 public void setValue(Object object, Object value) throws IllegalStateException, IllegalArgumentException {
23 Person root = (Person)object;
24
25 Address address = new Address();
26 String[] streets = ((String)value).split("\\|");
27 address.setStreet1(streets[0]);
28 address.setStreet2(streets[1]);
29
30 root.setAddress(address);
31 }
32
33 public void resetValue(Object object) throws IllegalStateException, IllegalArgumentException {
34 }
35
36 public void checkValidity(Object object) throws ValidityException, IllegalStateException {
37
38 }
39
40 public Object newInstance(Object parent) throws IllegalStateException {
41 return null;
42 }
43}这个 Handler 可没有 JAXB 相对应的 Adapter 那么好理解,要复杂的多,习惯下吧。
6. mapping.xml,映射文件,应该能看到它所表达的意思:
1<?xml version="1.0"?>
2<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
3 "http://castor.org/mapping.dtd"><br/><br/>
4<mapping>
5 <class name="cc.unmi.castor.PersonList"><br/><br/>
6 <field name="persons" collection="arraylist" type="cc.unmi.castor.Person">
7 <bind-xml name="Person" node="element" />
8 </field>
9 </class><br/><br/>
10 <class name="cc.unmi.castor.Person">
11 <map-to xml="Person" /><br/><br/>
12 <field name="name" type="java.lang.String">
13 <bind-xml name="Name" node="element" />
14 </field><br/><br/>
15 <field name="address" type="string"
16 handler="cc.unmi.castor.AddressHandler">
17 <bind-xml name="Address" node="element"/>
18 </field><br/><br/>
19 <field name="type" type="java.lang.String">
20 <bind-xml name="i:Type" QName-prefix="i" node="attribute"
21 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
22 </field>
23 </class><br/><br/>
24</mapping>上面有几点得好好看清楚下:
1) class 节点用 name 指定类型
2) field 节点用 type 指定类型
3) node 属性有是 element 也有对应于 attribute
4) address 的 type 为 string,而不是 cc.unmi.castor.Address,写成后者会报错的。
5) 对于 type 节点有 Namespace 时,写法确实很啰嗦的。不过如果在 castor.properties 的配置 suppressNamespaces 为 true 则可以忽略掉 Namespace。
7. Client.java,最后是客户端调用代码:
1package cc.unmi.castor;
2
3import java.io.InputStream;
4import java.net.URL;
5
6import org.exolab.castor.mapping.Mapping;
7import org.exolab.castor.xml.Unmarshaller;
8import org.xml.sax.InputSource;
9
10
11public class Client {
12
13 public static void main(String[] args) throws Exception{
14 Mapping mapping = new Mapping();
15 URL urlMapping = ClassLoader.getSystemResource("mapping.xml");
16 mapping.loadMapping(urlMapping);
17 Unmarshaller unmarshaller = new Unmarshaller(PersonList.class);
18 unmarshaller.setMapping(mapping);
19
20 InputStream xmlInputStream = ClassLoader.getSystemResourceAsStream("persons.xml");
21 InputSource inputSource = new InputSource(xmlInputStream);
22 PersonList personList = (PersonList)unmarshaller.unmarshal(inputSource);
23 System.out.println(personList.getPersons());
24 }
25}执行上面的代码控制台输出结果为:
[Unmi,st1|st2,worker, Fantasia,sz|gd,yuan]
结果正确。
最后还是说要用好下 Castor,请仔细阅读 http://www.castor.org/reference/html/XML%20data%20binding.html。原以为 Castor 的资料比 JAXB 少,现在才知道错了。而且就这样稍加深入的了解了下,发现 Castor 确实够强悍的。
参考:1. http://www.castor.org/xml-mapping.html
2. http://castor.org/spring-xml-intro.html
3. http://www.castor.org/xml-framework.html
4. http://www.castor.org/reference/html/XML%20data%20binding.html 永久链接 https://yanbin.blog/castor-xml-to-javabean-2/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。