Elim的博客

用来记录一些原创性的总结


Elim

JAXB之XMLAnyElement之对象转XML

在上一篇文章中介绍了使用@XmlAnyElement处理匹配任意XML元素转换为对象的场景,本文将介绍使用XmlAnyElement将对象转换为XML。
考虑如下这样的代码场景,我们有一个AnyObjHolder类,其拥有一个objs类型的属性,该属性中可以存放任意类型的元素。为了简单一点,我们假设它可以存放的类型只会有AnyObj1、AnyObj2或者AnyObj3。那么它生成的XML会是什么样呢?

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="holder")
class AnyObjHolder {
	
	private List<Object> objs;

	public List<Object> getObjs() {
		return objs;
	}

	public void setObjs(List<Object> objs) {
		this.objs = objs;
	}
	
}

@XmlAccessorType(XmlAccessType.FIELD)
class AnyObj1 {
	private String abc;

	public String getAbc() {
		return abc;
	}

	public void setAbc(String abc) {
		this.abc = abc;
	}
}

@XmlAccessorType(XmlAccessType.FIELD)
class AnyObj2 {
	private String abc;

	public String getAbc() {
		return abc;
	}

	public void setAbc(String abc) {
		this.abc = abc;
	}
}

@XmlAccessorType(XmlAccessType.FIELD)
class AnyObj3 {
	private String abc;

	public String getAbc() {
		return abc;
	}

	public void setAbc(String abc) {
		this.abc = abc;
	}
}

正常情况下它生成的XML会是如下这样:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<holder>
    <objs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="anyObj1">
        <abc>123</abc>
    </objs>
    <objs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="anyObj2">
        <abc>123</abc>
    </objs>
    <objs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="anyObj3">
        <abc>123</abc>
    </objs>
</holder>

如果我们期望AnyObj1类型的对象生成的XML的根节点是obj1,AnyObj2类型的对象生成的XML的根节点是obj2,AnyObj3类型的对象生成的XML的根节点是obj3。这个时候我们就可以把objs使用@XmlAnyElement修饰,在AnyObj1类上通过@XmlRootElement(name=”obj1”)指定生成的节点的名称为obj1,在AnyObj2类上通过@XmlRootElement(name=”obj2”)指定生成的节点的名称为obj2,在AnyObj3类上通过@XmlRootElement(name=”obj3”)指定生成的节点的名称为obj3。

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="holder")
class AnyObjHolder {
	
	@XmlAnyElement
	private List<Object> objs;

	public List<Object> getObjs() {
		return objs;
	}

	public void setObjs(List<Object> objs) {
		this.objs = objs;
	}
	
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="obj1")
class AnyObj1 {
	private String abc;

	public String getAbc() {
		return abc;
	}

	public void setAbc(String abc) {
		this.abc = abc;
	}
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="obj2")
class AnyObj2 {
	private String abc;

	public String getAbc() {
		return abc;
	}

	public void setAbc(String abc) {
		this.abc = abc;
	}
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="obj3")
class AnyObj3 {
	private String abc;

	public String getAbc() {
		return abc;
	}

	public void setAbc(String abc) {
		this.abc = abc;
	}
}

这样生成的XML会是如下这样:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<holder>
    <obj1>
        <abc>123</abc>
    </obj1>
    <obj2>
        <abc>123</abc>
    </obj2>
    <obj3>
        <abc>123</abc>
    </obj3>
</holder>

看到这里,可能你会想这跟我们之前介绍的@XmlElementRef有类似的效果。乍一看是类似的,实际上@XmlElementRef是用于父类和子类的关系,且List<Object> objs这里指定的泛型需要是对应的父类型,且不能是Object类型,这就是它们之间的差别。

(本文由Elim写于2017年9月11日)