xStream可以Java和xml相互转换。下面主要说明xstream读取xml文件(和xstream将Java转化成xml差不多)。本次学习用到的是xstream1.4.7
项目中使用到的xml文件
<config name="personconfig">
<!-- <add> --> <!-- 使用addImplicitCollection可以不出现 -->
<address>
<add>abc;abc</add>
<zipcode>zip#efg</zipcode>
</address>
<address>
<add>abcfe;123</add>
<zipcode>zipaf#695</zipcode>
</address>
<!-- </add> -->
</config>
保存xml的Java类,其中add存储xml里的所有Address节点信息。
对于不是用注解方式的:
package com.core;import java.util.ArrayList;
import java.util.List;public class Person {
private String name;/**
* add名称必须和包含Address的父节点一致,否则数据读取失败(除非使用了addImplicitCollection,则可以不出现<add>
*/
public List<Address> add = new ArrayList<Address>();public String getName() {
return name;
}public class Address {
private String add; //不一定要给出get/set方法,没有仍然可以从xml读取,这里给出get是因为要读取数据
private String zipcode;
public String getAdd() {
return add;
}
public String getZipcode() {
return zipcode;
}}
}
读取xml主类:
package com.core;import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import com.core.Person.Address;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;public class XStreamUtils {
private String fileName = "xstream.xml";public XStreamUtils() {
XStream xstream = new XStream(new DomDriver()); //还可以使用new StaxDriver(),官网推荐xpp3(最快解析xml,但是对于解析程序的配置文件,一般DomDriver和StaxDriver都够了)
//指明类与xml里的element对应关系,如果不指明,则element必须详细到类,如<com.core.Person>
xstream.alias("address", Address.class);
xstream.alias("config", Person.class);xstream.useAttributeFor(Person.class,"name"); //读取element attribute配置
//the addImplicitCollection method call: it describes which class and which member variable shall assume the behaviour we described.
xstream.addImplicitCollection(Person.class, "add"); //此声明可以使得address的父节点不需要出现<add>
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
Person p = (Person) xstream.fromXML(in);
System.out.println(p.add.get(1).getZipcode());
System.out.println(p.getName());
}public static void main(String[] args) {
XStreamUtils x = new XStreamUtils();
}
}
注:如果要xml要映射到的Java类里有list的属性(如上面的public List<Address>
add),如果address的父节点没有add,而代码里没有使用
addImplicitCollection(Person.class, "add"),则程序会抛出异常。
xstream不要求xml对应的Java类的属性一定要有get和set方法,没有也是可以成功的(估计是用了反射)。
2.使用注解:
package com.annotations;import java.util.ArrayList;
import java.util.List;import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamImplicit;/**
* 使用Java annotation
* @author
*
*/
@XStreamAlias("config") //声明在xml中的节点名称
public class Person {@XStreamAsAttribute //说明这个值是取自节点attribute
private String name;@XStreamImplicit //Address节点父节点无需是add
public List<Address> add = new ArrayList<Address>();public String getName() {
return name;
}@XStreamAlias("address")
public class Address {
//操作add子节点的内容,将结果放入add中
@XStreamConverter(value= SplitConverter.class,strings={";"})
private List<String> add; // 不一定要给出get/set方法,没有仍然可以从xml读取,这里给出get是因为要读取数据@XStreamConverter(value= SplitConverter.class,strings={"#"})
private List<String> zipcode;public void toAddressList() {
System.out.println("address start" + add.size());
for(String s : add) {
System.out.print(s + "\t");
}
System.out.println("address end");
}public void toZipCodeList() {
System.out.println("zipcode start" + zipcode.size());
for(String s : zipcode) {
System.out.print(s + "\t");
}
System.out.println("zipcode end");
}}
}
SplitConverter实现(Converter可以将xml里某个节点的内容根据需要转换成Java类里面需要的类型,反之亦然。可以使用
@XStreamConverter(value= SplitConverter.class,strings={";"}来重用converter):
SplitConverte作用:将某个节点的内容按照给定的分割符分割。
package com.annotations;import java.util.ArrayList;
import java.util.List;import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;/**
* 将某个节点的数据根据已给的分割符进行分割
* @author
*
*/
public class SplitConverter implements Converter {private String partionSymbol;
public SplitConverter() {
super();
}public SplitConverter(String str) {
super();
this.partionSymbol = str;
}/**
* 判断是否可以convert
*/
@Override
public boolean canConvert(Class arg0) {
// TODO Auto-generated method stub
return true;
}/**
* 写xml时,Java属性特殊处理
*/
@Override
public void marshal(Object arg0, HierarchicalStreamWriter arg1,
MarshallingContext arg2) {
// TODO Auto-generated method stub}
/**
* 读取xml数据时对某个节点的数据操作
*/
@Override
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext arg1) {
// TODO Auto-generated method stub
List<String> list = null;
String content = reader.getValue();
String[] arr = content.split(this.partionSymbol);
if(null != arr) {
list = new ArrayList<String>(arr.length);
for(String s : arr) {
list.add(s);
}
}
return list;
}}
注解 Main类:
package com.annotations;import java.io.InputStream;
import com.annotations.Person.Address;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;public class AnnotationMain {
private String fileName = "xstream.xml";
public AnnotationMain() {
XStream xstream = new XStream(new DomDriver());
//说明注解了哪些些类
xstream.processAnnotations(Person.class);
xstream.processAnnotations(Address.class);
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
Person p = (Person) xstream.fromXML(in);
p.add.get(0).toAddressList();
p.add.get(1).toZipCodeList();
}public static void main(String[] args) {
// TODO Auto-generated method stub
AnnotationMain a = new AnnotationMain();
}}
附:
Xstream常用注解:
@XStreamAlias("message")
:
别名注解
作用目标: 类,字段
@XStreamImplicit
隐式集合
@XStreamImplicit(itemFieldName="subElementName")
作用目标:
集合字段
@XStreamConverter(SingleValueCalendarConverter.class)
//不传入参数的
注入转换器
作用目标: 对象
@XStreamAsAttribute 转换成属性
作用目标:
字段
@XStreamOmitField 忽略字段
作用目标: 字段
此次学习时的测试项目在:http://pan.baidu.com/s/1tjzNC