用来记录一些原创性的总结
考虑这样一种场景,你有一个元素上面会有很多不同的属性,这些属性是动态的,你不能完全预知到其中会包含哪些属性,或者属性太多了你不能一一把它们列举出来与对象的属性一一对应。这样才情景我们就可以通过一个Map来接收这些动态的属性,然后在上面使用@XmlAnyAttribute,这样在转换为对象时JAXB就会把那些不能精确匹配到对应的属性上的XML元素属性映射到对应的Map上。假设有类似下面这样一段XML需要应用动态的属性匹配。
<holder prop1="value1" prop2="value2" prop3="value3"/>
可以建立类似下面这样的代码进行匹配,需要注意的是Map对应的Key需要是javax.xml.namespace.QName
类型的。
@XmlRootElement(name="holder")
@XmlAccessorType(XmlAccessType.FIELD)
class AnyAttributeHolder {
@XmlAnyAttribute
private Map<QName, String> attrs;
public Map<QName, String> getAttrs() {
return attrs;
}
public void setAttrs(Map<QName, String> attrs) {
this.attrs = attrs;
}
}
可以进行验证如下:
@Test
public void test2() {
String xml = "<holder prop1=\"value1\" prop2=\"value2\" prop3=\"value3\"/>";
AnyAttributeHolder holder = JAXB.unmarshal(new StringReader(xml), AnyAttributeHolder.class);
Assert.assertTrue(holder.getAttrs().get(new QName("prop1")).equals("value1"));
Assert.assertTrue(holder.getAttrs().get(new QName("prop2")).equals("value2"));
Assert.assertTrue(holder.getAttrs().get(new QName("prop3")).equals("value3"));
}
如果你还有把它marshal为XML的需要,也是可以进行的,如:
@Test
public void test() {
Map<QName, String> attrs = new HashMap<>();
for (int i=0; i<5; i++) {
attrs.put(new QName("prop" + (i+1)), "value" + (i+1));
}
AnyAttributeHolder holder = new AnyAttributeHolder();
holder.setAttrs(attrs);
StringWriter writer = new StringWriter();
JAXB.marshal(holder, writer);
System.out.println(writer);
}
生成的XML是如下这样:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<holder prop2="value2" prop1="value1" prop5="value5" prop4="value4" prop3="value3"/>
(注:本文由Elim写于2017年9月11日)