- java中XStream处理xml数据
- 一、简介
- 二、使用
- 2.1 XStream对象
- 2.1.1 创建XStream对象
- 2.1.2 XStream常用driver
- 2.1.3 XStream属性
- 2.2 常用注解
- 2.3 XStream转换方法
- 2.4 格式化xml字符串
- 三、示例
- 3.1 添加maven依赖
- 3.2 创建XStream对象
- 3.3 创建bean类
- 3.4 测试
- 四、更多
XStream是java类库,可以将java对象序列化为xml(或json)或反序列化为java对象。
二、使用 2.1 XStream对象在进行序列化前,先创建XStream对象,创建成功后不必重复创建(由于创建XStream会消耗大量资源,故大量创建XStream会存在性能问题),后续可复用,且XStream对象是线程安全。
2.1.1 创建XStream对象通过new方法即可简单创建XStream对象
public class XStreamFactory {
//初始化XStream对象,后续直接复用该对象(创建XStream对象开销大,大量重复创建会引发性能问题),Xstream是多线程安全的
//DomDriver类型
// private static XStream instance = new XStream(new DomDriver("UTF-8"));
//Xpp3Driver不会出现字段单下划线被转为双下划线问题
// private static XStream instance = new XStream(new Xpp3Driver(new NonameCoder()));
//StaxDriver类型
private static XStream instance = new XStream(new StaxDriver());
//获取XStream实例
public static XStream getXStreamInstance() {
return instance;
}
}
2.1.2 XStream常用driver
XStream对象初始化时需指定driver,XStream的driver有各种类型,常用的有:
JettisonMappedXmlDriver:依赖jettison库,可以obj转json, json转obj StaxDriver:序列化为xml DomDriver:序列化为xml JsonHierarchicalStreamDriver:不依赖其他库, obj转json StaxDriver:序列化为xml2.1.3 XStream属性
XStream对象初始化时可指定属性,常用属性有:
权限设置:可设置为最低,如:xStream.addPermission(AnyTypePermission.ANY); 设置是否注解解析:true是,false否,如:xStream.autodetectAnnotations(true); 引用设置:如存在引用时, 设置无引用模式xStream.setMode(XStream.NO_REFERENCES); 忽略未知元素:如 instance.ignoreUnknownElements();2.2 常用注解
@XStreamAlias: 指定别名,不使用注解时采用字段原始名称, 等价于:xStream.alias方法 @XStreamAsAttribute:指定以属性方式显示, 等价于:xStream.aliasField方法 @XStreamOmitField:xml忽略字段,等价于:xStream.omitField方法 @XStreamConverter:设置转换器, 等价于:xStream.registerConverter方法 @XStreamConverters:设置转换器 @XStreamImplicit:属性是数组或列表,不显示array或list字样, 等价于:xStream.addImplicitCollection方法2.3 XStream转换方法
toXML方法:序列化对象; fromXML方法:反序列化对象;2.4 格式化xml字符串
借助javax.xml.transform.Transformer类(SAXTransformerFactory.newInstance().newTransformer())可以格式化xml字符串,常用属性有:
设置缩进(yes:有缩进 no:没有缩进): 如transformer.setOutputProperty(OutputKeys.INDENT, "yes"),
设置编码:如transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
设置是否忽略xml声明(yes:忽略 no:不忽略):如transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
设置缩进字符数(仅在设置需要缩进时有效):如transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
三、示例
3.1 添加maven依赖
3.2 创建XStream对象org.projectlombok lombok com.thoughtworks.xstream xstream 1.4.11.1 compile
创建XStream对象工具类,使用getXStreamInstance获取XStream实例
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import com.thoughtworks.xstream.security.AnyTypePermission;
import org.xml.sax.InputSource;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class XStreamFactory {
//初始化XStream对象,后续直接复用该对象(创建XStream对象开销大,大量重复创建会引发性能问题),Xstream是多线程安全的
//DomDriver类型
// private static XStream instance = new XStream(new DomDriver("UTF-8"));
//Xpp3Driver不会出现字段单下划线被转为双下划线问题
private static XStream instance = new XStream(new Xpp3Driver(new NoNameCoder()));
//StaxDriver类型
//private static XStream instance = new XStream(new StaxDriver());
static {
//设置权限为最低
instance.addPermission(AnyTypePermission.ANY);
//开启注解解析
instance.autodetectAnnotations(true);
//存在引用时, 设置无引用模式
instance.setMode(XStream.NO_REFERENCES);
//忽略未知元素
instance.ignoreUnknownElements();
}
//获取XStream实例
public static XStream getXStreamInstance() {
return instance;
}
//格式化xml字符串
public static String formatXml(String xml){
try{
Transformer transformer = SAXTransformerFactory.newInstance().newTransformer();
//设置缩进, yes:有缩进 no:没有缩进
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//设置编码
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
//设置是否忽略xml声明, yes:忽略 no:不忽略
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
//设置缩进字符数,仅在设置需要缩进时有效
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
Source xmlSource = new SAXSource(new InputSource(new ByteArrayInputStream(xml.getBytes())));
StreamResult res = new StreamResult(new ByteArrayOutputStream());
transformer.transform(xmlSource, res);
xml = new String(((ByteArrayOutputStream) res.getOutputStream()).toByteArray());
}catch (Exception e){
}
return xml;
}
}
3.3 创建bean类
Teacher类
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("teacher")
public class Teacher {
private String name;
private String course;
}
TeacherItem类
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import lombok.*;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("teachers")
public class TeacherItem {
//@Singular可对集合内单个元素增加或删除
@Singular
//@XStreamImplicit表示不显示集合标签
@XStreamImplicit
private List teachers;
}
School类
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("school")
public class School {
private String name;
private String address;
}
Stu类
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("stu")
public class Stu {
//指定别名,默认为相同,不用指定
@XStreamAlias("stu_no")
private String no;
//以属性方式显示字段
@XStreamAsAttribute
private String name;
private School school;
private TeacherItem teacherItem;
}
3.4 测试
使用注解进行常规测试
import com.dragon.study.spring_boot_main.xstream.paper.bean.School;
import com.dragon.study.spring_boot_main.xstream.paper.bean.Stu;
import com.dragon.study.spring_boot_main.xstream.paper.bean.Teacher;
import com.dragon.study.spring_boot_main.xstream.paper.bean.TeacherItem;
import com.thoughtworks.xstream.XStream;
import org.springframework.util.Assert;
public class XStreamPaperMain {
public static void main(String[] args) {
//复用获取XStream实例
XStream xStream = XStreamFactory.getXStreamInstance();
School school = School.builder().name("中华小学").address("chengdu").build();
Teacher teacherOne = Teacher.builder().name("lin").course("math").build();
Teacher teacherTwo = Teacher.builder().name("liu").course("english").build();
TeacherItem teacherItem = TeacherItem.builder().teacher(teacherOne).teacher(teacherTwo).build();
Stu stu = Stu.builder().no("001").name("apple").school(school).teacherItem(teacherItem).build();
String xml = xStream.toXML(stu);
//直接转xml输出
System.out.println("原始xml输出:"+xml);
//格式化后输出
xml = XStreamFactory.formatXml(xml);
System.out.println("格式化xml输出:"+xml);
//反序列化为java对象
Stu newStu = (Stu) xStream.fromXML(xml);
Assert.notNull(newStu, "not null");
}
}
XStream的driver为Xpp3Driver输出结果为:
原始xml输出:格式化xml输出: 001 中华小学 chengdulin math liu english 001 中华小学 chengdulin math liu english
XStream的driver为StaxDriver(此时存在字段单下划线被转为双下划线问题,如下面字段stu__no ,可以通过字符串替换xml.replaceAll("__", “_”)解决)输出结果为:
原始xml输出:四、更多格式化xml输出: 001 中华小学 chengdulin math liu english 001 中华小学 chengdulin math liu english
XStream还可以自定义转化器,在此略过。



