XStream定制转换
 
XStream在实现Java、xml之间转换非常的出色。但也有一些问题需要解决:Java到XML,默认转换过去就使用Java成员属性的名字作为xml Element名,反过来亦如此。但这些都是不是实际中我们所要的结果。
 
为此,我又研读了XStream的文档,终于解决了这个问题,下面是测试代码。
 
package test;

import java.util.ArrayList;
import java.util.List;

/**
* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2008-5-21 10:48:43

* Note: 主体信息
*/

public class MainBody {
     private int id;
     private String name;
     private List investorList = new ArrayList();

     public MainBody( int id, String name, List investorList) {
         this.id = id;
         this.name = name;
         this.investorList = investorList;
    }


     public String toString() {
         return "MainBody{" +
                 "id=" + id +
                 ", name='" + name + '\'' +
                 ", investorList=" + investorList +
                '}';
    }
}
 
package test;

/**
* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2008-5-21 10:51:08

* Note: 投资人
*/

public class Investor {
     private int id;
     private String name;
     private int age;

     public Investor( int id, String name) {
         this.id = id;
         this.name = name;
    }

     public Investor( int id, String name, int age) {
         this.id = id;
         this.name = name;
         this.age = age;
    }

     public String toString() {
         return "Investor{" +
                 "id=" + id +
                 ", name='" + name + '\'' +
                 ", age='" + age + '\'' +
                '}';
    }
}
 
package test;

import com.thoughtworks.xstream.XStream;

import java.util.List;
import java.util.ArrayList;

/**
* Created by IntelliJ IDEA.

* User: leizhimin

* Date: 2008-5-21 10:54:05

* Note: 测试
*/

public class TestConvert {

     public static void main(String args[]) {
        test();
    }

     public static void test() {
        System.out.println( "----------test()----------");
        Investor investor1 = new Investor(1, "gaici");
        Investor investor2 = new Investor(2, "hahhah", 33);
        List investorList = new ArrayList();
        investorList.add(investor1);
        investorList.add(investor2);
        MainBody mainBody = new MainBody(1000, "微软", investorList);

        XStream xStream = new XStream();

         /************** 别名定义 Object -> xml ***************/

         //没有做任何别名定义直接转换
        outXML(1, xStream, mainBody);

         //类别名
        xStream.alias( "MainBody", test.MainBody. class);
        xStream.alias( "Investor", test.Investor. class);
        outXML(2, xStream, mainBody);

         //列表节点别名
        xStream.aliasField( "Investor-List", MainBody. class, "investorList");
        outXML(3, xStream, mainBody);

         //一般属性节点别名
        xStream.aliasField( "ztbs", test.MainBody. class, "id");
        xStream.aliasField( "gdbs", test.Investor. class, "id");
        outXML(4, xStream, mainBody);

         //将name成员作为属性添加到Investor对应xml节点里
//        xStream.aliasAttribute(Investor.class,"name","GDXM");
        xStream.useAttributeFor(Investor. class, "name");
        outXML(5, xStream, mainBody);

        xStream.aliasAttribute(Investor. class, "age", "NL");
        xStream.useAttributeFor(Investor. class, "age");
        outXML(6, xStream, mainBody);

         /***********************xml -> Object*************************/
        String newxml = "\n" +
                 "  1000\n" +
                 "  微软\n" +
                 "  \n" +
                 "    \n" +
                 "      1\n" +
                 "    
\n" +
                 "    \n" +
                 "      2\n" +
                 "    
\n" +
                 "  \n" +
                 "";
        MainBody m = (MainBody) xStream.fromXML(newxml);
        System.out.println( "将最后一次所得的xml结果转换为Java对象输出:");
        System.out.println(m);
    }

     public static void outXML( int index, XStream xStream, MainBody m) {
        String xml = xStream.toXML(m);
        System.out.println( ">>>>>>>>>>第" + index + "次输出XML:");
        System.out.println(xml + "\n");
    }
}
 
运行结果:
----------test()----------
>>>>>>>>>>第1次输出XML:
< test.MainBody >
   < id >1000 id >
   < name >微软 name >
   < investorList >
     < test.Investor >
       < id >1 id >
       < name >gaici name >
       < age >0 age >
     test.Investor >
     < test.Investor >
       < id >2 id >
       < name >hahhah name >
       < age >33 age >
     test.Investor >
   investorList >
test.MainBody >

>>>>>>>>>>第2次输出XML:
< MainBody >
   < id >1000 id >
   < name >微软 name >
   < investorList >
     < Investor >
       < id >1 id >
       < name >gaici name >
       < age >0 age >
     Investor >
     < Investor >
       < id >2 id >
       < name >hahhah name >
       < age >33 age >
     Investor >
   investorList >
MainBody >

>>>>>>>>>>第3次输出XML:
< MainBody >
   < id >1000 id >
   < name >微软 name >
   < Investor-List >
     < Investor >
       < id >1 id >
       < name >gaici name >
       < age >0 age >
     Investor >
     < Investor >
       < id >2 id >
       < name >hahhah name >
       < age >33 age >
     Investor >
   Investor-List >
MainBody >

>>>>>>>>>>第4次输出XML:
< MainBody >
   < ztbs >1000 ztbs >
   < name >微软 name >
   < Investor-List >
     < Investor >
       < gdbs >1 gdbs >
       < name >gaici name >
       < age >0 age >
     Investor >
     < Investor >
       < gdbs >2 gdbs >
       < name >hahhah name >
       < age >33 age >
     Investor >
   Investor-List >
MainBody >

>>>>>>>>>>第5次输出XML:
< MainBody >
   < ztbs >1000 ztbs >
   < name >微软 name >
   < Investor-List >
     < Investor name ="gaici" >
       < gdbs >1 gdbs >
       < age >0 age >
     Investor >
     < Investor name ="hahhah" >
       < gdbs >2 gdbs >
       < age >33 age >
     Investor >
   Investor-List >
MainBody >

>>>>>>>>>>第6次输出XML:
< MainBody >
   < ztbs >1000 ztbs >
   < name >微软 name >
   < Investor-List >
     < Investor name ="gaici" NL ="0" >
       < gdbs >1 gdbs >
     Investor >
     < Investor name ="hahhah" NL ="33" >
       < gdbs >2 gdbs >
     Investor >
   Investor-List >
MainBody >

将最后一次所得的xml结果转换为Java对象输出:
MainBody{id=1000, name='微软', investorList=[Investor{id=1, name='gaici', age='0'}, Investor{id=2, name='hahhah', age='33'}]}

Process finished with exit code 0
 
还有一个测试:
 
 
运行结果:
----------test()----------
MainBody{id=1000, name='微软', investorList=[Investor{id=1, name='gaici', age='0'}, Investor{id=2, name='hahhah', age='0'}]}
Investor{id=1, name='gaici', age='0'}
Investor{id=2, name='hahhah', age='0'}
Investor{id=2, name='hahhah', age='0'}

Process finished with exit code 0
 
 
说明:
1、XStream不要求Java类的属性必须有getter、setter方法,因此省略。
 
2、设置java成员属性别名
        xStream.aliasField("Investor-List",MainBody.class,"investorList");
        outXML(3,xStream,mainBody);
运行结果会产生:
 
 
3、将java成员映射为xml元素的一个属性
 
        //将name成员作为属性添加到Investor对应xml节点里       
        xStream.useAttributeFor(Investor.class,"name");
 
运行结果会产生:
           
 
 
下面这两句是相关联的:
        xStream.aliasAttribute(Investor.class,"name","GDXM");
        xStream.useAttributeFor(Investor.class,"name");
        意思是先为java成员定义个别名,然后在将别名应用于xml属性上。
 
运行结果会产生:
           
 
这些问题虽然解决了,但又发现了新的问题:xml转java时,当java中没有定义xml元素节点时,这时候会抛出异常。也许通过XStream本身的API可以解决,也许是XStream本身所不能处理的问题,时间有限,也没来得及深究。有知道的朋友,还望留言。
 
4、再进行xml到java 的转换过程中,XStream对象别名可以定义很多,涵盖的类的范围超过xml所能表达的范围,这个也没有关系,XStream还是会忠实地将xml还原为对象。但是如果xml范围大于XStream所涵盖类的范围,那么转换过程会出错。比如,要将一个Investor节点转换为ManiBody对象,肯定会出错。