xml 与 Java bean的互相转换

依赖

  1. <dependency>
  2. <groupId>com.thoughtworks.xstream</groupId>
  3. <artifactId>xstream</artifactId>
  4. <version>1.4.15</version>
  5. </dependency>

xml -> bean

创建XStream对象

  1. XStream xStream = new XStream(new StaxDriver());
  2. //安全配置,允许所有类型
  3. XStream.setupDefaultSecurity(xStream);
  4. xStream.allowTypesByRegExp(new String[]{".*"});
  5. //设定node节点对应的名称和java类型
  6. xStream.alias("X1Request", X1Request.class);
  7. //打开注解支持
  8. xStream.autodetectAnnotations(true);
  9. //xml转换为bean
  10. X1Request o = (X1Request) xStream.fromXML(new File(xmlPath));

整个转换过程中,xml节点的前的命名空间会被忽略

对于集合类型的属性,需要增加注解,请参照下方bean -> xml中相关描述

bean -> xml

调用方法

  1. //设定root节点名称为附带命名空间
  2. xStream.alias("ns1:X1Request", X1Request.class);
  3. //javabean 转xml
  4. String xml = xStream.toXML(o);

因为需要在每个节点增加命名空间前缀,对所有属性使用@XStreamAlias注解

  1. @XStreamAlias("ns1:x1RequestMessage")
  2. private X1RequestMessage x1RequestMessage;

对于集合类型的属性,需要在属性上增加如下注解XStreamImplicit,如果没有,会造成xml转bean报错或无法赋值

同时,泛型类型上需要增加别名,否则xml中为包路径

  1. @XStreamImplicit
  2. private List<TargetIdentifier> targetIdentifier;
  3. //同时需要在子类型上增加别名
  4. @XStreamAlias("ns1:targetIdentifier")
  5. public class TargetIdentifier {

正确的输出

  1. <ns1:targetIdentifiers>
  2. <ns1:targetIdentifier>
  3. <ns1:e164Number>447700900000</ns1:e164Number>
  4. </ns1:targetIdentifier>
  5. </ns1:targetIdentifiers>

错误的输出

  1. <ns1:targetIdentifiers>
  2. <com.example.demo.bean.TargetIdentifier>
  3. <ns1:e164Number>447700900000</ns1:e164Number>
  4. </com.example.demo.bean.TargetIdentifier>
  5. </ns1:targetIdentifiers>

对于集合类型,但泛型为String/Long等简单类型,只需要在XStreamImplicit的属性itemFieldName设定输出后的属性名称即可

  1. @XStreamImplicit(itemFieldName = "ns1:dID")
  2. private List<String> dId;

正确的输出

  1. <ns1:listOfDIDs>
  2. <ns1:dID>19867c20-8c94-473e-b9cd-8b72b7b05fd4</ns1:dID>
  3. </ns1:listOfDIDs>

错误的输出

  1. <ns1:listOfDIDs>
  2. <string>19867c20-8c94-473e-b9cd-8b72b7b05fd4</string>
  3. </ns1:listOfDIDs>

命名空间,在命名空间对应属性赋值,并添加XStreamAlias和XStreamAsAttribute注解

因为xstream是通过unsafe.allocateInstance,直接生成对象,会跳过一切初始化代码,包括静态代码块和new 方法,所以命名空间对应属性需要手动调用方法赋值

  1. @XStreamAlias("xmlns:ns")
  2. @XStreamAsAttribute
  3. private String ns;
  4. @XStreamAlias("xmlns:xsi")
  5. @XStreamAsAttribute
  6. private String xsi;
  7. public void setNameSpace(){
  8. this.ns = "http://uri.etsi.org/03221/X1/2017/10";
  9. this.xsi = "http://www.w3.org/2001/XMLSchema-instance";
  10. }

输出结果

  1. <ns1:X1Request
  2. xmlns:ns="http://uri.etsi.org/03221/X1/2017/10"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">