使用xStream进行java object<-->xml之间的转换

  1. 完成java object和xml之间的转换方法有多种。一种是利用xtream,一种是利用hibernate的第三方工具。
  2. xtream非常简单,不需要生成dtd,无用配置,不需要生成辅助类,虽然功能相对其他的同类工具要简单,但是基本上都能满足需要。
  3. hibernate有第三方工具,可以方便的在xml/obj/db之间转换。 
  4. xtream+xpp也是一个很好的选择
  5. public static void write() {   
  6.     XStream sm = new XStream();   
  7.     mytest t = new mytest();   
  8.     t.setName("moogle");   
  9.     t.setXb("男");   
  10.     try {   
  11.     FileOutputStream ops = new FileOutputStream(new File("C:\\111.xml"));   
  12.     sm.toXML(t, ops);   
  13.     ops.close();   
  14.     } catch (Exception e) {   
  15.         e.printStackTrace();   
  16.     }   
  17. }      
  18. public static void read() {   
  19.     XStream sm = new XStream(new DomDriver());   
  20.     try {   
  21.         FileInputStream ops = new FileInputStream(new File("C:\\111.xml"));   
  22.         mytest t = (mytest)sm.fromXML(ops);   
  23.         System.out.println(t.getName());   
  24.         ops.close();   
  25.         } catch (Exception e) {   
  26.             e.printStackTrace();   
  27.         }          

生成的XML文件内容:

xml 代码
  1. <mytest>  
  2.   <name>asd</name>  
  3.   <xb>男</xb>  
  4. </mytest>  


问题:
1.生成的xml文档没有<!---->

2.如果生成的文档中含有中文,比如上文代码中setXb("男")
在读取的时候会报

[Fatal Error] :4:7: Invalid byte 2 of 2-byte UTF-8 sequence.

解决办法

    1. 加入xpp3_min-1.1.3.4.O.jar(包含在xStream压缩包中) 
      将 
      XStream sm = new XStream(new DomDriver());

      XStream sm = new XStream();

 

不需要生成dtd,无用配置,不需要生成辅助类,速度快。这就是xstream+xpp超强黄金组合。
xstream大家都知道啦,XML Pull Parser是一种高速的 解析xml文件的方式,速度要比传统方式快很多(发现pull式解析现在比较流行了)。下面我给出多种使用方法的例子。


 

1.最简单的使用方法
因为这个太简单,所以我从moogle的blog http://moogle.javaeye.com/blog/34661取下面的例子
   1.  public static void write() {   
   2.     XStream sm = new XStream();   
   3.     mytest t = new mytest();   
   4.     t.setName("moogle");   
   5.     t.setXb("男");   
   6.     try {   
   7.     FileOutputStream ops = new FileOutputStream(new File("C://111.xml"));   
   8.     sm.toXML(t, ops);   
   9.     ops.close();   
  10.     } catch (Exception e) {   
  11.         e.printStackTrace();   
  12.     }   
  13. }      
  14. public static void read() {   
  15.     XStream sm = new XStream(new DomDriver());   
  16.     try {   
  17.         FileInputStream ops = new FileInputStream(new File("C://111.xml"));   
  18.         mytest t = (mytest)sm.fromXML(ops);   
  19.         System.out.println(t.getName());   
  20.         ops.close();   
  21.         } catch (Exception e) {   
  22.             e.printStackTrace();   
  23.         }          
  24. }

生成 XML是
# <mytest>  
#   <name>asd</name>  
#   <xb>男</xb>


 
2.中等方法(需要1.2版以上才有这个功能)
XStream stream = new XStream();
stream.alias("schema", SchemaObject.class);
stream.useAttributeFor("url", String.class);
stream.useAttributeFor("jdbcDriverClass", String.class);
stream.useAttributeFor("user", String.class);
stream.useAttributeFor("password", String.class);
FileOutputStream s = new FileOutputStream(file);
stream.toXML(theObject, s);
s.close();
alias和useAttributeFor是用作把 <com.hongsoft.model.SchemaObject>修改为<schema>


 

3.高级方法
XStream stream = new XStream();
stream.registerConverter(new SchemaXMLConvertor());
stream.alias("schema", SchemaObject.class);
FileInputStream s = new FileInputStream(file);
object = (SchemaObject) stream.fromXML(s);
s.close();

 


registerConverter可以实现把任何schema的XML和object互相转换,这个其实已经否定了很多朋友说的
“xstream+xpp”功能不强的说法。SchemaXMLConvertor示例如下:

 


public void marshal(Object arg0, HierarchicalStreamWriter writer,
            MarshallingContext arg2) {
    SchemaObject schema=(SchemaObject)arg0;        
    writer.startNode(SchemaObject.TABLE);
    writer.addAttribute(SchemaObject.TABLE_NAME, iTable.getName());
    //line            
    List<SchemaObject.TableObject.LineObject> lines=iTable.getLines();
    for(int j=0;j<lines.size();j++)
    {
        SchemaObject.TableObject.LineObject jLine=lines.get(j);
        writer.startNode(SchemaObject.LINE);
        //column
        Map<String,String> columns=jLine.getColumns();
        Iterator ite=columns.keySet().iterator();
        while(ite.hasNext())
        {
            String columnName=ite.next().toString();
            writer.addAttribute(columnName, columns.get(columnName));
        }
        writer.endNode();
        }
        writer.endNode();
        writer.underlyingWriter();
    }

public Object unmarshal(HierarchicalStreamReader reader,
            UnmarshallingContext arg1) {
    SchemaObject schema=new SchemaObject();
    schema.setJdbcDriverClass(reader.getAttribute(SchemaObject.JDBC_DRIVER_CLASS));
    schema.setUrl(reader.getAttribute(SchemaObject.URL));
    schema.setUser(reader.getAttribute(SchemaObject.USER));
    schema.setPassword(reader.getAttribute(SchemaObject.PASSWORD));
    List<TableObject> tables = new ArrayList<TableObject>();
        while(reader.hasMoreChildren()) {
            reader.moveDown();
            SchemaObject.TableObject table=new SchemaObject().new TableObject();
            table.setName(reader.getAttribute(SchemaObject.TABLE_NAME));
            tables.add(table);
            reader.moveUp();
        }
        schema.setTables(tables);        
        return schema;
}
public boolean canConvert(Class arg0) {
    return arg0.equals(SchemaObject.class);
}

 

 

 

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

posted on 2014-01-26 16:02  山庄听泉  阅读(1363)  评论(1编辑  收藏  举报

导航