简单动态XML
关于简单动态XML
有一点需要注意,之前所有指定的字段都指定了数据,但是如果不指定数据,就能生成不一样的XML
@Test
public void test4() throws JAXBException {
Product p1 = new Product();
p1.setId("11041");
Product p2 = new Product();
p2.setId("11042");
p2.setName("Grape");
List<Product> list = Arrays.asList(p1,p2);
Order3 order = new Order3();
order.setId("1104");
order.setProduct(list);
JAXBContext context = JAXBContext.newInstance(Order3.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(order, System.out);
}
生成的XML只包含上面指定数据的字段。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order>
<id>1104</id>
<Products>
<product id="11041"/>
<product id="11042">
<name>Grape</name>
</product>
</Products>
</Order>
动态 XML Element
有时候,Products元素下面并不只是加入 product ,可能动态加入这种商品。 这次的模拟的商品是糕点与饼干。
这里的 Cake 只包含一个字段,需要注意的是 @XmlRootElement
不能少。
@XmlRootElement(name = "Cake")
public class Cake {
private String name;
//setters, getters
}
这里的 Biscuit 也只包含一个字段。
@XmlRootElement(name = "Biscuit")
public class Biscuit {
private String name;
//setters, getters
}
Order的第三个字段是List,但是没有指定一个特定对象,用了Object代指所有,还有一个@XmlAnyElement
是最重要的注解,用来标注所有的Element。
@XmlRootElement(name = "Order")
@XmlAccessorType(XmlAccessType.FIELD)
public class Order4 {
private String id;
private Double price;
@XmlElementWrapper(name = "Products")
@XmlAnyElement
private List<Object> product;
//setters, getters
}
下面用来模拟数据生成,注意的是JAXBContext需要注册所有需要编组的Java bean。这一点和之前的例子是不同的。
@Test
public void test4() throws JAXBException {
Cake cake = new Cake();
cake.setName("Nobel");
Biscuit biscuit = new Biscuit();
biscuit.setName("PB");
List<Object> list = Arrays.asList(cake,biscuit);
Order4 order = new Order4();
order.setId("1104");
order.setProduct(list);
JAXBContext context = JAXBContext.newInstance(Order4.class, Cake.class, Biscuit.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(order, System.out);
}
生成的XML包含了一个 Products ,其数据结构在Order中并没有指定,方便后期扩展。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order>
<id>1104</id>
<Products>
<Cake>
<name>Nobel</name>
</Cake>
<Biscuit>
<name>PB</name>
</Biscuit>
</Products>
</Order>
XML 动态 Attribute
与动态Element对应的是Attribute,不过需要注意的是,动态 Attribute 需要的是 Map ,而且其 key 的类型需要指定为 QName
,这个QName
在复杂的 XML 生成时有很大用处。一般使用到的是其QName(name)
,它还有一个形式为QName(name,namespace)
,可以指定命名空间,在某些场景下有不可替代的作用。
@XmlRootElement(name = "Order")
@XmlAccessorType(XmlAccessType.FIELD)
public class Order5 {
@XmlAnyAttribute
private Map<QName, String> properties;
private Product product;
//setters, getters
}
@Test
public void test5() throws JAXBException {
Product p = new Product();
p.setId("1100");
p.setName("Apple");
Map<QName, String> map = new HashMap<>();
map.put(new QName("id"), "1105");
map.put(new QName("classification"), "food");
map.put(new QName("type"), "fruit");
Order5 order = new Order5();
order.setProduct(p);
order.setProperties(map);
JAXBContext context = JAXBContext.newInstance(Order5.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(order, System.out);
}
仅关注 Order 的 Attribute , 可以发现我们在 Order 中没有指定任何与之相关的字段,只是在HashMap
中加了几组数据,现在编组成为了Attribute。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order id="1105" classification="food" type="fruit">
<product id="1100">
<name>Apple</name>
</product>
</Order>