Java 操作 XML(13)--XStream 使用
XStream 是一种 OXMapping 技术,主要实现将 java 对象和 XML 绑定的功能,类似 JAXB。本文主要介绍 XStream 的基本使用,文中所使用到的软件版本:Java 1.8.0_181、XStream 1.4.15。
1、简介
XStream 是一个Java对象和XML相互转换的工具,提供了所有的基础类型、数组、集合等类型直接转换的支持。XStream 使用起来非常简单,不需要预先生成相关的辅助类,不需要映射文件;当然,使用简单也注定了它只能处理简单结构的 XML 文件。官网地址为:http://x-stream.github.io/
1.1、序列化重命名
在Java对象转XML的过程中,可以设置类或字段对应的XML节点名称、设置字段为XML的属性、隐藏字段等;看参考官网:http://x-stream.github.io/alias-tutorial.html。
1.1.1、包重命名:XStream.aliasPackage
xstream.aliasPackage("com.abc.demo.general.xml", "demo")
1.1.2、类重命名:XStream.alias
xstream.alias("grade", Grade.class);
1.1.3、字段重命名:XStream.aliasField
xstream.aliasField("age", Student.class, "age");
1.1.4、省略集合根节点:XStream.addImplicitCollection
xstream.addImplicitCollection(Grade.class, "students");
1.1.5、字段设置成XML属性:XStream.useAttributeFor
xstream.useAttributeFor(Student.class, "rollno");
1.1.6、隐藏字段:XStream.omitField
xstream.omitField(Student.class, "marks");
1.2、自定义转换器
自定义转换器需实现com.thoughtworks.xstream.converters.Converter接口,看参考官网地址:http://x-stream.github.io/converter-tutorial.html。
public class MyConvert implements Converter { /** * Java对象转成XML */ @Override public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext context) { ... } /** * XML转Java对象 */ @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { ... } @Override public boolean canConvert(Class type) { ... } }
1.3、XStream注解
使用Xstream注解前需要对XStream进行配置:应用某个JavaBean类的注解或自动使用检测类的注解;看参考官网地址:http://x-stream.github.io/annotations-tutorial.html。
XStream xstream = new XStream(); xstream.processAnnotations(GradeXStream.class); xstream.autodetectAnnotations(true);
1.3.1、重命名:@XStreamAlias
@XStreamAlias("grade")
1.3.2、省略集合根节点:@XStreamImplicit
@XStreamImplicit
1.3.3、字段设置成XML属性:@XStreamAsAttribute
@XStreamAsAttribute
1.3.4、隐藏字段:@XStreamOmitField
@XStreamOmitField
1.3.5、设置转换器:@XStreamConverter
@XStreamConverter(value= BooleanConverter.class, booleans={true, false}, strings={"男","女"})
2、XStream使用例子
2.1、引入依赖
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.15</version> </dependency>
2.2、XML样例文件
<?xml version="1.0" encoding="utf-8" ?> <school:grade xmlns:school="http://www.w3.org/TR/html4/school/"> <school:student rollno="1" age="11"> <school:firstname>cxx1</school:firstname> <school:lastname>Bob1</school:lastname> <school:nickname>stars1</school:nickname> <school:marks>85</school:marks> </school:student> <school:student rollno="2" age="12"> <school:firstname>cxx2</school:firstname> <school:lastname>Bob2</school:lastname> <school:nickname>stars2</school:nickname> <school:marks>85</school:marks> </school:student> <school:student rollno="3" age="13"> <school:firstname>cxx3</school:firstname> <school:lastname>Bob3</school:lastname> <school:nickname>stars3</school:nickname> <school:marks>85</school:marks> </school:student> </school:grade>
2.3、XML对应实体类
2.3.1、无注解
package com.abc.demo.general.xml; import java.util.List; /** * 班级 */ public class Grade { private List<Student> students; public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } @Override public String toString() { return "Grade{" + "students=" + students + '}'; } }
package com.abc.demo.general.xml; /** * 学生 */ public class Student { private int rollno; private int age; private String firstname; private String lastname; private String nickname; private String marks; public Student() {} public Student(int rollno, int age, String firstname, String lastname, String nickname, String marks) { this.rollno = rollno; this.age = age; this.firstname = firstname; this.lastname = lastname; this.nickname = nickname; this.marks = marks; } public int getRollno() { return rollno; } public void setRollno(int rollno) { this.rollno = rollno; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public String getMarks() { return marks; } public void setMarks(String marks) { this.marks = marks; } @Override public String toString() { return "Student{" + "rollno=" + rollno + ", age=" + age + ", firstname='" + firstname + '\'' + ", lastname='" + lastname + '\'' + ", nickname='" + nickname + '\'' + ", marks='" + marks + '\'' + '}'; } }
2.3.2、使用XStream的注解
package com.abc.demo.general.xml; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamImplicit; import java.util.List; /** * 班级 */ @XStreamAlias("grade") public class GradeXStream { @XStreamImplicit private List<StudentXStream> students; public List<StudentXStream> getStudents() { return students; } public void setStudents(List<StudentXStream> students) { this.students = students; } @Override public String toString() { return "GradeXStream{" + "students=" + students + '}'; } }
package com.abc.demo.general.xml; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamOmitField; /** * 学生 */ @XStreamAlias("student") public class StudentXStream { @XStreamAsAttribute private int rollno; @XStreamAsAttribute private int age; private String firstname; private String lastname; private String nickname; @XStreamOmitField private String marks; public StudentXStream() {} public StudentXStream(int rollno, int age, String firstname, String lastname, String nickname, String marks) { this.rollno = rollno; this.age = age; this.firstname = firstname; this.lastname = lastname; this.nickname = nickname; this.marks = marks; } public int getRollno() { return rollno; } public void setRollno(int rollno) { this.rollno = rollno; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public String getMarks() { return marks; } public void setMarks(String marks) { this.marks = marks; } @Override public String toString() { return "StudentXStream{" + "rollno=" + rollno + ", age=" + age + ", firstname='" + firstname + '\'' + ", lastname='" + lastname + '\'' + ", nickname='" + nickname + '\'' + ", marks='" + marks + '\'' + '}'; } }
2.4、使用例子
2.4.1、基本使用
/** * java对象转成xml * @throws Exception */ @Test public void javaToXml() { List<Student> students = new ArrayList<>(); Student student1 = new Student(1, 11,"cxx1", "Bob1", "stars1", "85"); Student student2 = new Student(2, 12, "cxx2", "Bob2", "stars2", "85"); Student student3 = new Student(3, 13, "cxx3", "Bob3", "stars3", "85"); students.add(student1); students.add(student2); students.add(student3); Grade grade = new Grade(); grade.setStudents(students); QNameMap qNameMap = new QNameMap(); qNameMap.setDefaultNamespace("http://www.w3.org/TR/html4/school/"); qNameMap.setDefaultPrefix("school"); // qNameMap.registerMapping(new QName("http://www.w3.org/TR/html4/school/", "school"), ClassXStream.class); XStream xstream = new XStream(new StaxDriver(qNameMap)); //设置类对应的节点名称 xstream.alias("grade", Grade.class); xstream.alias("student", Student.class); //设置类字段对应的节点名称 xstream.aliasField("age", Student.class, "age"); xstream.aliasField("firstname", Student.class, "firstname"); //省略集合根节点 xstream.addImplicitCollection(Grade.class, "students"); //把类字段设置成属性 xstream.useAttributeFor(Student.class, "rollno"); xstream.useAttributeFor(Student.class, "age"); //隐藏类字段 xstream.omitField(Student.class, "marks"); String xml = xstream.toXML(grade); logger.info(xml); } /** * xml转成java对象 * @throws Exception */ @Test public void xmlToJava() { QNameMap qNameMap = new QNameMap(); qNameMap.setDefaultNamespace("http://www.w3.org/TR/html4/school/"); qNameMap.setDefaultPrefix("school"); XStream xstream = new XStream(new StaxDriver(qNameMap)); xstream.ignoreUnknownElements(); //设置类对应的节点名称 xstream.alias("grade", Grade.class); xstream.alias("student", Student.class); //设置类字段对应的节点名称 xstream.aliasField("age", Student.class, "age"); xstream.aliasField("firstname", Student.class, "firstname"); //省略集合根节点 xstream.addImplicitCollection(Grade.class, "students"); //把类字段设置成属性 xstream.useAttributeFor(Student.class, "rollno"); xstream.useAttributeFor(Student.class, "age"); Grade grade = (Grade) xstream.fromXML(XStreamCase.class.getResourceAsStream("student3.xml")); logger.info(grade.toString()); }
2.4.2、使用自定义转换器
定义自定义转换器:
package com.abc.demo.general.xml; 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; import java.util.ArrayList; import java.util.List; /** * 自定义转换器 */ public class GradeConvert implements Converter { /** * Java对象转成XML */ @Override public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext context) { Grade grade = (Grade) o; List<Student> students = grade.getStudents(); writer.addAttribute("xmlns:school", "http://www.w3.org/TR/html4/school/"); for (Student student : students) { writer.startNode("school:student"); writer.addAttribute("rollno", student.getRollno() + ""); writer.addAttribute("age", student.getAge() + ""); writer.startNode("school:firstname"); writer.setValue(student.getFirstname()); writer.endNode(); writer.startNode("school:lastname"); writer.setValue(student.getLastname()); writer.endNode(); writer.startNode("school:nickname"); writer.setValue(student.getNickname()); writer.endNode(); writer.startNode("school:marks"); writer.setValue(student.getMarks()); writer.endNode(); writer.endNode(); } } /** * XML转Java对象 */ @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { Grade grade = new Grade(); List<Student> students = new ArrayList<>(); grade.setStudents(students); while (reader.hasMoreChildren()) { Student student = new Student(); students.add(student); reader.moveDown(); student.setRollno(Integer.parseInt(reader.getAttribute("rollno"))); student.setAge(Integer.parseInt(reader.getAttribute("age"))); reader.moveDown(); student.setFirstname(reader.getValue()); reader.moveUp(); reader.moveDown(); student.setLastname(reader.getValue()); reader.moveUp(); reader.moveDown(); student.setNickname(reader.getValue()); reader.moveUp(); reader.moveDown(); student.setMarks(reader.getValue()); reader.moveUp(); reader.moveUp(); } return grade; } @Override public boolean canConvert(Class type) { return type.equals(Grade.class); } }
转换器使用:
/** * java对象转成xml(自定义转换器) * @throws Exception */ @Test public void javaToXmlCustomerConvert() { List<Student> students = new ArrayList<>(); Student student1 = new Student(1, 11,"cxx1", "Bob1", "stars1", "85"); Student student2 = new Student(2, 12, "cxx2", "Bob2", "stars2", "85"); Student student3 = new Student(3, 13, "cxx3", "Bob3", "stars3", "85"); students.add(student1); students.add(student2); students.add(student3); Grade grade = new Grade(); grade.setStudents(students); XStream xstream = new XStream(new StaxDriver()); xstream.alias("school:grade", Grade.class); xstream.registerConverter(new GradeConvert()); String xml = xstream.toXML(grade); logger.info(xml); } /** * xml转成java对象(自定义转换器) * @throws Exception */ @Test public void xmlToJavaCustomerConvert() { QNameMap qNameMap = new QNameMap(); qNameMap.setDefaultNamespace("http://www.w3.org/TR/html4/school/"); qNameMap.setDefaultPrefix("school"); XStream xstream = new XStream(new StaxDriver(qNameMap)); xstream.alias("grade", Grade.class); xstream.ignoreUnknownElements(); xstream.registerConverter(new GradeConvert()); Grade grade = (Grade) xstream.fromXML(XStreamCase.class.getResourceAsStream("student3.xml")); logger.info(grade.toString()); }
2.4.3、使用XStream注解
/** * java对象转成xml(注解) * @throws Exception */ @Test public void javaToXmlAnnotation() { List<StudentXStream> students = new ArrayList<>(); StudentXStream student1 = new StudentXStream(1, 11,"cxx1", "Bob1", "stars1", "85"); StudentXStream student2 = new StudentXStream(2, 12, "cxx2", "Bob2", "stars2", "85"); StudentXStream student3 = new StudentXStream(3, 13, "cxx3", "Bob3", "stars3", "85"); students.add(student1); students.add(student2); students.add(student3); GradeXStream grade = new GradeXStream(); grade.setStudents(students); QNameMap qNameMap = new QNameMap(); qNameMap.setDefaultNamespace("http://www.w3.org/TR/html4/school/"); qNameMap.setDefaultPrefix("school"); XStream xstream = new XStream(new StaxDriver(qNameMap)); xstream.autodetectAnnotations(true); String xml = xstream.toXML(grade); logger.info(xml); } /** * xml转成java对象(注解) * @throws Exception */ @Test public void xmlToJavaAnnotation() { QNameMap qNameMap = new QNameMap(); qNameMap.setDefaultNamespace("http://www.w3.org/TR/html4/school/"); qNameMap.setDefaultPrefix("school"); XStream xstream = new XStream(new StaxDriver(qNameMap)); xstream.ignoreUnknownElements(); xstream.autodetectAnnotations(true); xstream.processAnnotations(GradeXStream.class); GradeXStream grade = (GradeXStream) xstream.fromXML(XStreamCase.class.getResourceAsStream("student3.xml")); logger.info(grade.toString()); }
2.5、完整例子
package com.abc.demo.general.xml; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.QNameMap; import com.thoughtworks.xstream.io.xml.StaxDriver; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; /** * XStream使用 */ public class XStreamCase { private static Logger logger = LoggerFactory.getLogger(XStreamCase.class); /** * java对象转成xml * @throws Exception */ @Test public void javaToXml() { List<Student> students = new ArrayList<>(); Student student1 = new Student(1, 11,"cxx1", "Bob1", "stars1", "85"); Student student2 = new Student(2, 12, "cxx2", "Bob2", "stars2", "85"); Student student3 = new Student(3, 13, "cxx3", "Bob3", "stars3", "85"); students.add(student1); students.add(student2); students.add(student3); Grade grade = new Grade(); grade.setStudents(students); QNameMap qNameMap = new QNameMap(); qNameMap.setDefaultNamespace("http://www.w3.org/TR/html4/school/"); qNameMap.setDefaultPrefix("school"); // qNameMap.registerMapping(new QName("http://www.w3.org/TR/html4/school/", "school"), ClassXStream.class); XStream xstream = new XStream(new StaxDriver(qNameMap)); //设置类对应的节点名称 xstream.alias("grade", Grade.class); xstream.alias("student", Student.class); //设置类字段对应的节点名称 xstream.aliasField("age", Student.class, "age"); xstream.aliasField("firstname", Student.class, "firstname"); //省略集合根节点 xstream.addImplicitCollection(Grade.class, "students"); //把类字段设置成属性 xstream.useAttributeFor(Student.class, "rollno"); xstream.useAttributeFor(Student.class, "age"); //隐藏类字段 xstream.omitField(Student.class, "marks"); String xml = xstream.toXML(grade); logger.info(xml); } /** * xml转成java对象 * @throws Exception */ @Test public void xmlToJava() { QNameMap qNameMap = new QNameMap(); qNameMap.setDefaultNamespace("http://www.w3.org/TR/html4/school/"); qNameMap.setDefaultPrefix("school"); XStream xstream = new XStream(new StaxDriver(qNameMap)); xstream.ignoreUnknownElements(); //设置类对应的节点名称 xstream.alias("grade", Grade.class); xstream.alias("student", Student.class); //设置类字段对应的节点名称 xstream.aliasField("age", Student.class, "age"); xstream.aliasField("firstname", Student.class, "firstname"); //省略集合根节点 xstream.addImplicitCollection(Grade.class, "students"); //把类字段设置成属性 xstream.useAttributeFor(Student.class, "rollno"); xstream.useAttributeFor(Student.class, "age"); Grade grade = (Grade) xstream.fromXML(XStreamCase.class.getResourceAsStream("student3.xml")); logger.info(grade.toString()); } /** * java对象转成xml(自定义转换器) * @throws Exception */ @Test public void javaToXmlCustomerConvert() { List<Student> students = new ArrayList<>(); Student student1 = new Student(1, 11,"cxx1", "Bob1", "stars1", "85"); Student student2 = new Student(2, 12, "cxx2", "Bob2", "stars2", "85"); Student student3 = new Student(3, 13, "cxx3", "Bob3", "stars3", "85"); students.add(student1); students.add(student2); students.add(student3); Grade grade = new Grade(); grade.setStudents(students); XStream xstream = new XStream(new StaxDriver()); xstream.alias("school:grade", Grade.class); xstream.registerConverter(new GradeConvert()); String xml = xstream.toXML(grade); logger.info(xml); } /** * xml转成java对象(自定义转换器) * @throws Exception */ @Test public void xmlToJavaCustomerConvert() { QNameMap qNameMap = new QNameMap(); qNameMap.setDefaultNamespace("http://www.w3.org/TR/html4/school/"); qNameMap.setDefaultPrefix("school"); XStream xstream = new XStream(new StaxDriver(qNameMap)); xstream.alias("grade", Grade.class); xstream.ignoreUnknownElements(); xstream.registerConverter(new GradeConvert()); Grade grade = (Grade) xstream.fromXML(XStreamCase.class.getResourceAsStream("student3.xml")); logger.info(grade.toString()); } /** * java对象转成xml(注解) * @throws Exception */ @Test public void javaToXmlAnnotation() { List<StudentXStream> students = new ArrayList<>(); StudentXStream student1 = new StudentXStream(1, 11,"cxx1", "Bob1", "stars1", "85"); StudentXStream student2 = new StudentXStream(2, 12, "cxx2", "Bob2", "stars2", "85"); StudentXStream student3 = new StudentXStream(3, 13, "cxx3", "Bob3", "stars3", "85"); students.add(student1); students.add(student2); students.add(student3); GradeXStream grade = new GradeXStream(); grade.setStudents(students); QNameMap qNameMap = new QNameMap(); qNameMap.setDefaultNamespace("http://www.w3.org/TR/html4/school/"); qNameMap.setDefaultPrefix("school"); XStream xstream = new XStream(new StaxDriver(qNameMap)); xstream.autodetectAnnotations(true); String xml = xstream.toXML(grade); logger.info(xml); } /** * xml转成java对象(注解) * @throws Exception */ @Test public void xmlToJavaAnnotation() { QNameMap qNameMap = new QNameMap(); qNameMap.setDefaultNamespace("http://www.w3.org/TR/html4/school/"); qNameMap.setDefaultPrefix("school"); XStream xstream = new XStream(new StaxDriver(qNameMap)); xstream.ignoreUnknownElements(); xstream.autodetectAnnotations(true); xstream.processAnnotations(GradeXStream.class); GradeXStream grade = (GradeXStream) xstream.fromXML(XStreamCase.class.getResourceAsStream("student3.xml")); logger.info(grade.toString()); } }