动态子节点
动态子节点
既然使用 JAXBElement
可以动态指定参数值,如果某个Java 字段使用该类型是否可以做到动态生成XML子节点呢: Yes & No。
定义一个零食,第二个参数是 JAXBElement
的 水果,Fruit
在之前一定定义过了。
@XmlRootElement
public class Food {
private String name;
private JAXBElement<Fruit> element;
// setters,getters
}
这里还需要指定一个 ObjectFactory
,ObjectFactory 类型的类里面可以定义一些创建某种类型的对象的方法,@XmlRegistry
用于标注在充当ObjectFactory角色的类上,@XmlElementDecl
声明对应的元素定义,其方法的返回值需要是JAXBElement类型,并且它必须指定一个name
,这个name自由赋值,这里指定为'ref1'备用。
customElement 方法我直接返回null,因为实现细节不需要在这里写死,等下创建对象的时候再声明。
@XmlRegistry
public class ObjectFactory {
@XmlElementDecl(name = "ref1")
public JAXBElement<Fruit> customElement(Fruit fruit){
return null;
}
}
在Food
中定义了 JAXBElement<Fruit>
,需要使用 @XmlElementRef(name="ref1")
关联使用到了 ObjectFactory
哪个方法,可以把@XmlElementRef(name="ref1")
标注在对应的setter/getter方法上,或者标注在字段上,不过需要注意的是标注在字段上,还需要指定@XmlAccessorType(XmlAccessType.FIELD)
.
我习惯将注解标注在字段上,所以需要加
@XmlAccessorType
,如果加在get方法上就不需要加@XmlAccessorType
.
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Food {
private String name;
@XmlElementRef(name="ref1")
private JAXBElement<Fruit> element;
// setters,getters
// @XmlElementRef(name="ref1")
public JAXBElement<Fruit> getElement() {
return element;
}
}
测试一下上面的写法是否正确。
@Test
public void test4() throws JAXBException {
Fruit fruit = new Fruit();
fruit.setColor("red");
JAXBElement<Fruit> element = new JAXBElement<Fruit>(new QName("时令水果"), Fruit.class, fruit);
Food food = new Food();
food.setName("Some foods");
food.setElement(element);
JAXBContext context = JAXBContext.newInstance(Fruit.class,Food.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(food, System.out);
}
可以看到XML的子节点Fruit
并不是之前指定的@XmlRootElement
,而是测试代码中设置的值。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<food>
<name>Some foods</name>
<时令水果>
<color>red</color>
</时令水果>
</food>
更改QName
的值为‘生鲜水果’,发现生成的XML跟着变化。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<food>
<name>Some foods</name>
<生鲜水果>
<color>red</color>
</生鲜水果>
</food>