XML文件解析之XStream的初步使用

1 篇文章 0 订阅

Xstream个人觉得是一个挺简单的XML解析工具,使用一些注解就可以简单完成xml数据和java实体之间的转换。sxtream还支持对流的操作。这里只讲简单的字符串数据和实体之间的转换。

一、依赖

        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.11.1</version>
        </dependency>

二、一些常用的注解

这边只讲自己用到,比较熟悉的4个注解,后面如果有使用到其余的注解在补充

1、@XStreamAlias 用于实体类或者字段上,可以设置别名,相当于alias方法。

/**
 * Annotation used to define an XStream class or field alias.
 * @see com.thoughtworks.xstream.XStream#alias(String, Class)
 * @see com.thoughtworks.xstream.XStream#alias(String, Class, Class)
 * @see com.thoughtworks.xstream.XStream#addDefaultImplementation(Class, Class)
 */

2、@XStreamAsAttribute

把字段作为xml文件节点中的属性

3、@XStreamImplicit

可以去除节点中的集合或数组元素

4、@XStreamConverter

可以使用我们自定义的格式来转换,如date转为各种样式的string

三、使用

先简单建立一个班级-学生关系的类。

SchoolClass.java
@Data
public class SchoolClass {

    private String className;

    private String classMaster;

    private Song song;

    private List<Student> studentList;
}


Song.java
@Data
public class Song {

    private String name;

    private String author;
}

Student.java
@Data
public class Student {

    private int id;

    private String name;

    private int age;

    private Date birthDay;
}

1、类转字符串

这边赋值后转成xml

public class SchoolXmlTest {

    public static void main(String[] args) {
        beanToString();
    }

    public static void beanToString(){

        SchoolClass class1 = new SchoolClass();
        class1.setClassName("班级1");
        class1.setClassMaster("班主任1");
        Song classSong = new Song();
        classSong.setName("班歌");
        class1.setSong(classSong);
        List<Student> students = new ArrayList<>();
        class1.setStudentList(students);
        Student student1 = new Student();
        student1.setId(1);
        student1.setName("学生1");
        student1.setAge(19);
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, 2000);
        calendar.set(Calendar.MONTH, 0);
        calendar.set(Calendar.DATE, 1);
        student1.setBirthDay(calendar.getTime());
        students.add(student1);
        Student student2 = new Student();
        student2.setId(2);
        student2.setName("学生2");
        student2.setAge(16);
        students.add(student2);

        XStream stream = new XStream();
        String result = stream.toXML(class1);
        System.out.println(result);
    }
}

打印的结果如下,肯定不是我们想要的数据

<xml.SchoolClass>
  <className>班级1</className>
  <classMaster>班主任1</classMaster>
  <song>
    <name>班歌</name>
  </song>
  <studentList>
    <xml.Student>
      <id>1</id>
      <name>学生1</name>
      <age>17</age>
      <birthDay>2000-01-01 03:07:42.300 UTC</birthDay>
    </xml.Student>
    <xml.Student>
      <id>2</id>
      <name>学生2</name>
      <age>16</age>
    </xml.Student>
  </studentList>
</xml.SchoolClass>

改一下SchoolClass和Student的类

@Data
@XStreamAlias("class")
public class SchoolClass {

    @XStreamAlias("class_name")
    private String className;

    private String classMaster;

    private Song song;

    @XStreamAlias("STUDENT")
//    @XStreamImplicit
    private List<Student> studentList;
}

@Data
@XStreamAlias("student")
public class Student {

    @XStreamAsAttribute
    private int id;

    private String name;

    private int age;

    @XStreamConverter(DateConverter.class)
    private Date birthDay;
}

我们想把Date按照我们想要的格式转为字符串,那就需要自定义一个转换的规则

当date作为节点时


public class DateConverter implements Converter {

    /**
     * bean转为xml
     * @param source
     * @param writer
     * @param context
     */
    @Override
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        Date date = (Date)source;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String time = format.format(date);
        writer.setValue(time);
    }

    /**
     * xml转成bean
     * @param reader
     * @param context
     * @return
     */
    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        if (StringUtils.isEmpty(reader.getValue())){
            return null;
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return format.parse(reader.getValue());
        } catch (ParseException e) {
            return null;
        }
    }

    @Override
    public boolean canConvert(Class type) {
        return Date.class == type;
    }
}

2、如果date字段作为属性,那么就要使用另外一种转换,并且要加上@XStreamAsAttribute注解

public class DateValueConverter implements SingleValueConverter {

    @Override
    public String toString(Object obj) {
        Date date = (Date)obj;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String time = format.format(date);
        return time;
    }

    @Override
    public Object fromString(String str) {
        if (StringUtils.isEmpty(str)){
            return null;
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return format.parse(str);
        } catch (ParseException e) {
            return null;
        }
    }

    @Override
    public boolean canConvert(Class type) {
        return Date.class == type;
    }
}

转换方法处在改动一下

        //new Xpp3Driver(new NoNameCoder())如果使用new XStream()构造,下划线_会变成__
        XStream stream = new XStream(new Xpp3Driver(new NoNameCoder()));
        //使用注解解析要设置为true
        stream.autodetectAnnotations(true);
        //@XStreamAlias相当于alias方法
//        stream.alias("class", SchoolClass.class);
        //有时候解析会在属性里出现class,<STUDENT class="singleton-list">,去除class
        stream.aliasSystemAttribute(null,"class");
        String result = stream.toXML(class1);
        System.out.println(result);

结果如下

<class>
  <class_name>班级1</class_name>
  <classMaster>班主任1</classMaster>
  <song>
    <name>班歌</name>
  </song>
  <STUDENT>
    <student id="1">
      <name>学生1</name>
      <age>17</age>
      <birthDay>2000-01-01</birthDay>
    </student>
  </STUDENT>
</class>

@XStreamImplicit注解可以去除上面的STUDENT节点,可以根据实际情况使用。

2、字符串转实体类

    public static void xmlToBean(){
        String xml = "<class>\n" +
                "  <class_name>班级1</class_name>\n" +
                "  <classMaster>班主任1</classMaster>\n" +
                "  <song>\n" +
                "    <name>班歌</name>\n" +
                "  </song>\n" +
                "  <STUDENT>\n" +
                "    <student id=\"1\">\n" +
                "      <name>学生1</name>\n" +
                "      <age>17</age>\n" +
                "    </student>\n" +
                "  </STUDENT>\n" +
                "</class>";
        XStream xStream = new XStream();
        xStream.autodetectAnnotations(true);
        //设置要转换的类
        xStream.processAnnotations(SchoolClass.class);
        SchoolClass schoolClass = (SchoolClass) xStream.fromXML(xml);
        System.out.println(schoolClass);
    }

打印结果

Security framework of XStream not initialized, XStream is probably vulnerable.
SchoolClass(className=班级1, classMaster=班主任1, song=Song(name=班歌, author=null), studentList=[Student(id=1, name=学生1, age=17)])

控制台打印结果有个安全警告,我们可以通过下面的方式处理

        XStream xStream = new XStream();
        XStream.setupDefaultSecurity(xStream);
        //自己实体类的路径
        xStream.allowTypesByWildcard(new String[]{"xml.*"});
        xStream.autodetectAnnotations(true);
        xStream.processAnnotations(SchoolClass.class);
        SchoolClass schoolClass = (SchoolClass) xStream.fromXML(xml);
        System.out.println(schoolClass);

三、整理成工具类

把xml和实体之间的转换弄成一个工具类。

public class XmlUtils {

    public static String beanToString(Object o){
        XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
        xStream.aliasSystemAttribute(null,"class");
        xStream.autodetectAnnotations(true);
        String result = xStream.toXML(o);
        return result;
    }


    public static <T>T stringToClass(String xml, Class<T> clazz){
        XStream xStream = new XStream();
        XStream.setupDefaultSecurity(xStream);
        //自己实体类的路径
        xStream.allowTypesByWildcard(new String[]{"xml.*"});
        xStream.autodetectAnnotations(true);
        xStream.processAnnotations(clazz);
        return clazz.cast(xStream.fromXML(xml));
    }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值