XStream对象相当Java对象和XML之间的转换器,转换过程是双向的。创建XSteam对象的方式很简单,只需要new XStream()即可。
Java到xml,用toXML()方法。
Xml到Java,用fromXML()方法。
在没有任何默认配置的情况下,java到xml的映射,是java成员名对应xml的元素名,java类的全名对应xml根元素的名字。而实际中,往往是xml和java类都有了,要完成相互转换,必须进行别名映射。
别名配置包含三种情况:
1、类别名,用alias(String name, Class type)。
2、类成员别名,用aliasField(String alias, Class definedIn, String fieldName)
3、 类成员作为属性别名,用 aliasAttribute(Class definedIn, String attributeName, String alias),单独命名没有意义,还要通过useAttributeFor(Class definedIn, String fieldName) 应用到某个类上。
XStream Annotation
@XStreamAlias("Alias Name"): used to alias Class name and field
@XStreamAsAttribute(): add attribute for Class
@XStreamImplicit() 或者@XStreamImplicit(itemFieldName = "Group")重新指定名字
XML解析器
1. XPP3 (需要 xpp3-[version].jar)
XStream xstream = new XStream(new XppDriver());
2. JAXP DOM
XStream xstream = new XStream(new DomDriver()); 不指定编码解析器
XStream xstream = new XStream(new DomDriver(“UTF-8”)); 指定编码解析器
XStreamd的一些小bug
--在定义别名中的下划线“_”转换为xml后会变成“__”这个符号. 因此,尽量避免在别名中实用任何符号,却是需要下划线的时候,可以考虑实用连接符“-”,这个没有问题。
--Java Bean中常常有一些常量,在转换过程,XStream也会将这些常量转换过去,形成常量的xml节点,这显然不是想要的结果,对于常量字段,就不做转换了。
代码清单1:
package test;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias("ADDRESS")
public class Address {
private String add;
@XStreamAsAttribute()
private String zipcode;
public Address(String add, String zipcode) {
this.add = add;
this.zipcode = zipcode;
}
public String toString() {
return "Address{"
+ "add='" + add + '\''
+ ", zipcode='" + zipcode + '\''
+ '}';
}
}
代码清单2:
package test;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import java.util.List;
@XStreamAlias("PERSON")
public class Person {
@XStreamAlias("Name")
private String name;
//使用@XStreamOmitField 对不生成xml的字段加注释
//然后代码中使用xstream.autodetectAnnotations(true); 就可以完成去掉属性了
@XStreamOmitField
private String age;
private Profile profile;
@XStreamImplicit()
private List<Address> addlist;
public Person(String name, String age, Profile profile, List<Address> addlist) {
this.name = name;
this.age = age;
this.profile = profile;
this.addlist = addlist;
}
public String toString() {
return "Person{"
+ "name='" + name + '\''
+ ", age='" + age + '\''
+ ", profile=" + profile
+ ", addlist=" + addlist
+ '}';
}
}
代码清单3:
package test;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("PROFILE")
public class Profile {
private String job;
private String tel;
private String remark;
public Profile(String job, String tel, String remark) {
this.job = job;
this.tel = tel;
this.remark = remark;
}
public String toString() {
return "Profile{"
+ "job='" + job + '\''
+ ", tel='" + tel + '\''
+ ", remark='" + remark + '\''
+ '}';
}
}
代码清单4:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test;
import com.thoughtworks.xstream.XStream;
import java.util.ArrayList;
import java.util.List;
public class TestXStream {
public static void main(String args[]) {
test();
}
public static void test() {
System.out.println("----------XStream学习:http://lavasoft.blog.51cto.com----------");
//目标对象
Address address1 = new Address("郑州市经三路", "450001");
Address address2 = new Address("西安市雁塔路", "710002");
List<Address> addList = new ArrayList<Address>();
addList.add(address1);
addList.add(address2);
Profile profile = new Profile("软件工程师", "13512129933", "备注说明");
Person person = new Person("熔岩", "27", profile, addList);
//转换装配
XStream xStream = new XStream();
/************** 设置类别名 ****************/
//xStream.alias("PERSON", test.Person.class);
//xStream.alias("PROFILE", test.Profile.class);
//xStream.alias("ADDRESS", test.Address.class);
//可将上面三句话换成下面一句,效果等价
xStream.processAnnotations(new Class[]{test.Person.class, test.Profile.class, test.Address.class});
output(1, xStream, person);
/************* 设置类成员的别名 ***************/
//设置Person类的name成员别名Name
xStream.aliasField("Name", Person.class, "name");
/*[注意] 设置Person类的profile成员别名PROFILE,这个别名和Profile类的别名一致,
* 这样可以保持XStream对象可以从profile成员生成的xml片段直接转换为Profile成员,
* 如果成员profile的别名和Profile的别名不一致,则profile成员生成的xml片段不可
* 直接转换为Profile对象,需要重新创建XStream对象,这岂不给自己找麻烦? */
xStream.aliasField("PROFILE", test.Person.class, "profile");
xStream.aliasField("ADDLIST", test.Person.class, "addlist");
xStream.aliasField("Add", test.Address.class, "add");
xStream.aliasField("Job", test.Profile.class, "job");
xStream.autodetectAnnotations(true);
output(2, xStream, person);
/******* 设置类成员为xml一个元素上的属性 *******/
xStream.useAttributeFor(test.Address.class, "zipcode");
/************* 设置属性的别名 ***************/
xStream.aliasAttribute(test.Address.class, "zipcode", "Zipcode");
output(3, xStream, person);
}
public static void output(int i, XStream xStream, Object obj) {
String xml = xStream.toXML(obj);
System.out.println(">>>第[ " + i + "]次输出\n");
System.out.println(xml + "\n");
}
}
读取配置文件:
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ConfigReader {
String datasourcename = null;
String ipaddress = null;
String logfilename = null;
String appender = null;
@Override
public String toString() {
return "Datasource Name : " + datasourcename
+ " \nIP Address : " + ipaddress
+ " \nLogfilename : " + logfilename
+ " \nAppender : " + appender;
}
public static void main(String[] args) throws FileNotFoundException {
XStream xs = new XStream(new DomDriver());
FileInputStream fis = new FileInputStream("c:/temp/Config.xml");
xs.aliasField("datasource-name", ConfigReader.class, "datasourcename");
xs.alias("config", ConfigReader.class);
ConfigReader r = (ConfigReader) xs.fromXML(fis);
System.out.println(r.toString());
}
}
配置文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<datasource-name>IRIS</datasource-name>
<ipaddress>9.124.74.85</ipaddress>
<logfilename>DailyLogApplication.log</logfilename>
<appender>console</appender>
</config>
忘记是从哪转载的了,望作者勿怪