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 +
                '}';
    }
}
Grade.java
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 + '\'' +
                '}';
    }
}
Student.java

 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 +
                '}';
    }
}
GradeXStream.java
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 + '\'' +
                '}';
    }
}
StudentXStream.java

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());
    }
}
XStreamCase.java

 

posted @ 2021-02-28 14:59  且行且码  阅读(1473)  评论(0编辑  收藏  举报