您可能希望这样做可能有一个有效的理由,但通常最好避免生成这种 XML。为什么?因为这意味着地图的 XML 元素依赖于地图的运行时内容。由于XML通常用作外部接口或接口层,因此这是不可取的。让我解释一下。
Xml 架构 (xsd) 定义 XML 文档的接口协定。除了能够从 XSD 生成代码之外,JAXB 还可以从代码中为您生成 XML 模式。这允许您将通过接换的数据限制为 XSD 中定义的预先商定的结构。
在 a 的默认情况下,生成的 XSD 将限制映射元素包含多个条目元素,每个元素必须包含一个键和一个值。这是一个非常清晰的界面契约。Map<String, String>
xs:string
xs:string
您描述的是,您希望 xml 映射包含其名称将在运行时由映射内容确定的元素。然后,生成的 XSD 只能指定映射必须包含编译时类型未知的元素列表。在定义接口协定时,通常应避免这种情况。
在这种情况下,若要实现严格的协定,应使用枚举类型作为映射的键,而不是 String。例如:
public enum KeyType {
KEY, KEY2;
}
@XmlJavaTypeAdapter(MapAdapter.class)
Map<KeyType , String> mapProperty;
这样,您希望成为 XML 中元素的键在编译时是已知的,因此 JAXB 应该能够生成一个模式,该模式将使用预定义的键 KEY 或 KEY2 之一将 map 的元素限制为元素。
另一方面,如果您希望简化默认生成的结构
<map>
<entry>
<key>KEY</key>
<value>VALUE</value>
</entry>
<entry>
<key>KEY2</key>
<value>VALUE2</value>
</entry>
</map>
对于像这样更简单的东西
<map>
<item key="KEY" value="VALUE"/>
<item key="KEY2" value="VALUE2"/>
</map>
您可以使用 MapAdapter 将 Map 转换为 MapElements 数组,如下所示:
class MapElements {
@XmlAttribute
public String key;
@XmlAttribute
public String value;
private MapElements() {
} //Required by JAXB
public MapElements(String key, String value) {
this.key = key;
this.value = value;
}
}
public class MapAdapter extends XmlAdapter<MapElements[], Map<String, String>> {
public MapAdapter() {
}
public MapElements[] marshal(Map<String, String> arg0) throws Exception {
MapElements[] mapElements = new MapElements[arg0.size()];
int i = 0;
for (Map.Entry<String, String> entry : arg0.entrySet())
mapElements[i++] = new MapElements(entry.getKey(), entry.getValue());
return mapElements;
}
public Map<String, String> unmarshal(MapElements[] arg0) throws Exception {
Map<String, String> r = new TreeMap<String, String>();
for (MapElements mapelement : arg0)
r.put(mapelement.key, mapelement.value);
return r;
}
}