java 利用Xstream生成和解析xml,知识结构:
1.Xstream简介;
使用限制: JDK版本不能<1.5.
虽然预处理注解是安全的,但自动侦查注解可能发生竞争条件.
特点:
简化的API;
无映射文件;
高性能,低内存占用;
整洁的XML;
不需要修改对象;支持内部私有字段,不需要setter/getter方法,final字段;非公有类,内部类;类不需要默认构造器,完全对象图支持.维护对象引用计数,循环引用. i
提供序列化接口;
自定义转换类型策略;
详细的错误诊断;
快速输出格式;当前支持 JSON 和 morphing.
使用场景
Transport 转换
Persistence 持久化对象
Configuration 配置
Unit Tests 单元测
隐式集合
当我们使用集合类时不想显示集合,只显示里面的元素即可.
使用隐式集合前:
<list>
<element />
<element />
<list>
使用隐式集合:
xstream.addImplicitCollection(Person.class, "list");
使用隐式集合后:
<element />
<element />
2.Xstream注解常用知识:
@XStreamAlias("message") 别名注解
作用目标: 类,字段
@XStreamImplicit 隐式集合
@XStreamImplicit(itemFieldName="part")
作用目标: 集合字段
@XStreamConverter(SingleValueCalendarConverter.class) 注入转换器
作用目标: 对象
@XStreamAsAttribute 转换成属性
作用目标: 字段
@XStreamOmitField 忽略字段
作用目标: 字段
Auto-detect Annotations 自动侦查注解
xstream.autodetectAnnotations(true);
自动侦查注解与XStream.processAnnotations(Class[] cls)的区别在于性能.自动侦查注解将缓存所有类的类型.
3.案例分析:
(1)同一标签下多个同名元素;
(2)同一标签下循环多个对象;
1.实体类:PersonBean
1 import java.util.List;
2
3 import com.thoughtworks.xstream.annotations.XStreamAlias;
4 import com.thoughtworks.xstream.annotations.XStreamImplicit;
5
6 /**
7 *@ClassName:PersonBean
8 *@author: chenyoulong Email: chen.youlong@payeco.com
9 *@date :2012-9-28 下午3:10:47
10 *@Description:TODO
11 */
12 @XStreamAlias("person")
13 public class PersonBean {
14 @XStreamAlias("firstName")
15 private String firstName;
16 @XStreamAlias("lastName")
17 private String lastName;
18
19 @XStreamAlias("telphone")
20 private PhoneNumber tel;
21 @XStreamAlias("faxphone")
22 private PhoneNumber fax;
23
24 //测试一个标签下有多个同名标签
25 @XStreamAlias("friends")
26 private Friends friend;
27
28 //测试一个标签下循环对象
29 @XStreamAlias("pets")
30 private Pets pet;
31
32
33 //省略setter和getter
34 }
2.实体类:PhoneNumber
1 @XStreamAlias("phoneNumber")
2 public class PhoneNumber{
3 @XStreamAlias("code")
4 private int code;
5 @XStreamAlias("number")
6 private String number;
7
8 //省略setter和getter
9
10 }
3.实体类:Friends(一个标签下有多个同名标签 )
1 /**
2 * 用Xstream注解的方式实现:一个标签下有多个同名标签
3 *@ClassName:Friends
4 *@author: chenyoulong Email: chen.youlong@payeco.com
5 *@date :2012-9-28 下午4:32:24
6 *@Description:TODO 5个name 中国,美国,俄罗斯,英国,法国
7 *
8 */
9 public static class Friends{
10 @XStreamImplicit(itemFieldName="name") //itemFieldName定义重复字段的名称,
11 /*<friends> <friends>
12 <name>A1</name> <String>A1</String>
13 <name>A2</name> 如果没有,则会变成 =====> <String>A1</String>
14 <name>A3</name> <String>A1</String>
15 </friends> </friends>
16 */
17 private List<String> name;
18
19 public List<String> getName() {
20 return name;
21 }
22
23 public void setName(List<String> name) {
24 this.name = name;
25 }
26 }
4.1实体类:Animal(同一标签下循环对象实体1)
1 //测试同一标签下循环某一对象
2 public class Animal{
3 @XStreamAlias("name")
4 private String name;
5 @XStreamAlias("age")
6 private int age;
7 public Animal(String name,int age){
8 this.name=name;
9 this.age=age;
10 }
11
12 //省略setter和getter
13 }
4.2实体类:Pets(同一标签下循环对象实体2)
1 /**
2 * 测试同一标签下循环某一对象
3 *@ClassName:Pets
4 *@author: chenyoulong Email: chen.youlong@payeco.com
5 *@date :2012-9-28 下午6:26:01
6 *@Description:TODO
7 */
8 public class Pets{
9 @XStreamImplicit(itemFieldName="pet")
10 private List<Animal> animalList;
11
12 public List<Animal> getAnimalList() {
13 return animalList;
14 }
15
16 public void setAnimalList(List<Animal> animalList) {
17 this.animalList = animalList;
18 }
19
20 }
5.main函数示例1:toxml
1 import com.thoughtworks.xstream.XStream;
2 import com.thoughtworks.xstream.io.json.JsonWriter.Format;
3 import com.thoughtworks.xstream.io.xml.DomDriver;
4
5 /**
6 *@ClassName:PersonTest
7 *@author: chenyoulong
8 *@date :2012-9-28 下午3:25:09
9 *@Description:TODO
10 */
11 public class PersonTest {
12
13 /**
14 * @Title: main
15 * @Description: TODO
16 * @param args
17 * @return void
18 */
19 public static void main(String[] args) {
20 // TODO Auto-generated method stub
21
22 PersonBean per=new PersonBean();
23 per.setFirstName("chen");
24 per.setLastName("youlong");
25
26 PhoneNumber tel=new PhoneNumber();
27 tel.setCode(137280);
28 tel.setNumber("137280968");
29
30 PhoneNumber fax=new PhoneNumber();
31 fax.setCode(20);
32 fax.setNumber("020221327");
33 per.setTel(tel);
34 per.setFax(fax);
35
36
37 //测试一个标签下有多个同名标签
38 List<String> friendList=new ArrayList<String>();
39 friendList.add("A1");
40 friendList.add("A2");
41 friendList.add("A3");
42 Friends friend1=new Friends();
43 friend1.setName(friendList);
44 per.setFriend(friend1);
45
46 //测试一个标签下循环对象
47 Animal dog=new Animal("Dolly",2);
48 Animal cat=new Animal("Ketty",2);
49 List<Animal> petList=new ArrayList<Animal>();
50 petList.add(dog);
51 petList.add(cat);
52 Pets pet=new Pets();
53 pet.setAnimalList(petList);
54 per.setPet(pet);
55
56 //java对象转换成xml
57 String xml=XmlUtil.toXml(per);
58 System.out.println("xml==="+xml);
59
60 }
61 }
xml效果图
1 xml===<person>
2 <firstName>chen</firstName>
3 <lastName>youlong</lastName>
4 <telphone>
5 <code>137280</code>
6 <number>137280968</number>
7 </telphone>
8 <faxphone>
9 <code>20</code>
10 <number>020221327</number>
11 </faxphone>
12 <friends>
13 <name>A1</name>
14 <name>A2</name>
15 <name>A3</name>
16 </friends>
17 <pets>
18 <pet>
19 <name>doly</name>
20 <age>2</age>
21 </pet>
22 <pet>
23 <name>Ketty</name>
24 <age>2</age>
25 </pet>
26 </pets>
27 </person>
5.2 main函数示例2:toBean
1 public static void main(String[] args) {
2 // TODO Auto-generated method stub
3
4 //toXml
5 // String xmlStr=new PersonTest().toXml();
6
7 //toBean
8 // PersonBean per=new PersonTest().toBean();
9 String xmlStr="<person>"+
10 "<firstName>chen</firstName>"+
11 "<lastName>youlong</lastName>"+
12 "<telphone>"+
13 "<code>137280</code>"+
14 "<number>137280968</number>"+
15 "</telphone>"+
16 "<faxphone>"+
17 "<code>20</code>"+
18 "<number>020221327</number>"+
19 "</faxphone>"+
20 "<friends>"+
21 "<name>A1</name>"+
22 "<name>A2</name>"+
23 "<name>A3</name>"+
24 "</friends>"+
25 "<pets>"+
26 "<pet>"+
27 "<name>doly</name>"+
28 "<age>2</age>"+
29 "</pet>"+
30 "<pet>"+
31 "<name>Ketty</name>"+
32 "<age>2</age>"+
33 "</pet>"+
34 "</pets>"+
35 "</person>";
36 //用泛型的知识
37 PersonBean person=XmlUtil.toBean(xmlStr, PersonBean.class);
38 System.out.println("person=firstname=="+person.getFirstName());
39 System.out.println("person==Friends==name1=="+person.getFriend().getName().get(0));
40 System.out.println("person==Pets==name2=="+person.getPet().getAnimalList().get(1).getName());
41
42 /*
43 //效果与以下方法类同,(以下代码较为直观)
44 XStream xstream=new XStream(new DomDriver()); //注意:不是new Xstream(); 否则报错:
45
46 xstream.processAnnotations(PersonBean.class);
47 PersonBean person=(PersonBean)xstream.fromXML(xmlStr);
48 System.out.println("person=firstname=="+person.getFirstName());
49 System.out.println("person==Friends==name1=="+person.getFriend().getName().get(0));
50 System.out.println("person==Pets==name=="+person.getPet().getAnimalList().get(1).getName());
51 */
52
53
54 }
6.XmlUtil工具类(toxml()和toBean())
1 /**
2 * 输出xml和解析xml的工具类
3 *@ClassName:XmlUtil
4 *@author: chenyoulong Email: chen.youlong@payeco.com
5 *@date :2012-9-29 上午9:51:28
6 *@Description:TODO
7 */
8 public class XmlUtil{
9 /**
10 * java 转换成xml
11 * @Title: toXml
12 * @Description: TODO
13 * @param obj 对象实例
14 * @return String xml字符串
15 */
16 public static String toXml(Object obj){
17 XStream xstream=new XStream();
18 // XStream xstream=new XStream(new DomDriver()); //直接用jaxp dom来解释
19 // XStream xstream=new XStream(new DomDriver("utf-8")); //指定编码解析器,直接用jaxp dom来解释
20
21 如果没有这句,xml中的根元素会是<包.类名>;或者说:注解根本就没生效,所以的元素名就是类的属性
22 xstream.processAnnotations(obj.getClass()); //通过注解方式的,一定要有这句话
23 return xstream.toXML(obj);
24 }
25
26 /**
27 * 将传入xml文本转换成Java对象
28 * @Title: toBean
29 * @Description: TODO
30 * @param xmlStr
31 * @param cls xml对应的class类
32 * @return T xml对应的class类的实例对象
33 *
34 * 调用的方法实例:PersonBean person=XmlUtil.toBean(xmlStr, PersonBean.class);
35 */
36 public static <T> T toBean(String xmlStr,Class<T> cls){
37 //注意:不是new Xstream(); 否则报错:java.lang.NoClassDefFoundError: org/xmlpull/v1/XmlPullParserFactory
38 XStream xstream=new XStream(new DomDriver());
39 xstream.processAnnotations(cls);
40 T obj=(T)xstream.fromXML(xmlStr);
41 return obj;
42 }
43
44 /**
45 * 写到xml文件中去
46 * @Title: writeXMLFile
47 * @Description: TODO
48 * @param obj 对象
49 * @param absPath 绝对路径
50 * @param fileName 文件名
51 * @return boolean
52 */
53
54 public static boolean toXMLFile(Object obj, String absPath, String fileName ){
55 String strXml = toXml(obj);
56 String filePath = absPath + fileName;
57 File file = new File(filePath);
58 if(!file.exists()){
59 try {
60 file.createNewFile();
61 } catch (IOException e) {
62 log.error("创建{"+ filePath +"}文件失败!!!" + Strings.getStackTrace(e));
63 return false ;
64 }
65 }// end if
66 OutputStream ous = null ;
67 try {
68 ous = new FileOutputStream(file);
69 ous.write(strXml.getBytes());
70 ous.flush();
71 } catch (Exception e1) {
72 log.error("写{"+ filePath +"}文件失败!!!" + Strings.getStackTrace(e1));
73 return false;
74 }finally{
75 if(ous != null )
76 try {
77 ous.close();
78 } catch (IOException e) {
79 log.error("写{"+ filePath +"}文件关闭输出流异常!!!" + Strings.getStackTrace(e));
80 }
81 }
82 return true ;
83 }
84
85 /**
86 * 从xml文件读取报文
87 * @Title: toBeanFromFile
88 * @Description: TODO
89 * @param absPath 绝对路径
90 * @param fileName 文件名
91 * @param cls
92 * @throws Exception
93 * @return T
94 */
95 public static <T> T toBeanFromFile(String absPath, String fileName,Class<T> cls) throws Exception{
96 String filePath = absPath +fileName;
97 InputStream ins = null ;
98 try {
99 ins = new FileInputStream(new File(filePath ));
100 } catch (Exception e) {
101 throw new Exception("读{"+ filePath +"}文件失败!", e);
102 }
103
104 String encode = useEncode(cls);
105 XStream xstream=new XStream(new DomDriver(encode));
106 xstream.processAnnotations(cls);
107 T obj =null;
108 try {
109 obj = (T)xstream.fromXML(ins);
110 } catch (Exception e) {
111 // TODO Auto-generated catch block
112 throw new Exception("解析{"+ filePath +"}文件失败!",e);
113 }
114 if(ins != null)
115 ins.close();
116 return obj;
117 }
118
119 }