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     }