我有一个类似以下的XML文件:
<root>
<item>
<id>my id</id>
<type>my type</id>
<key1>value1</key1>
<key2>value1</key2>
<key3>value1</key3>
</item>
<item>
<id>my id</id>
<type>my type</type>
<other-key1>value1</other-key1>
<other-key2>value1</other-key2>
</item>
(...)
</root>
我想在这样的类上解析XML:
public class Item {
private String id;
private String type;
private Map<String, String> values;
}
将id节点和类型节点映射到具有相同名称的属性,并将项目中的其他内容添加到地图中。
我尝试使用注释XmlJavaTypeAdapter和XmlAnyElement编写一个类,但这不符合我的预期:
(...)
public class Item {
@XmlElement
private String id;
@XmlElement
private String type;
@XmlAnyElement
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String, String> values;
}
public class MapAdapter extends XmlAdapter<Object, Map<String, String>> {
@Override
public Object marshal(Map<String, String> v) throws Exception {
}
@Override
public Map<String, String> unmarshal(Object v) throws Exception {
// v is a node instead an array of nodes.
// I want to get an array of nodes to convert them to a map.
//
// eg:
//
// key1 -> value1
// key2 -> value2
// key3 -> value3
//
}
知道我怎么能得到这个吗?
澄清我的问题:
我的问题是我想要在地图中解组的元素不在包装器中,并且它们与同一级别的其他元素混合。
我尝试使用XmlAnyElement和XmlJavaTypeAdapter来获取所有剩余元素的映射。但是这些注释有一个隐含的顺序,我得到的是用适配器解析的元素集合:
XmlAnyElement找到每个剩余的元素,用适配器解析它并将结果添加到集合中。
有没有办法扭转这种局面?
我想获得所有剩余元素的集合,然后使用XmlAdapter解析集合以获取地图。
答案 0 :(得分:1)
和你一样,我没有成功写出XmlAdapter
。
但还有另一种可能的方法:
在Item
班级中,声明List<Element>
注明了@XmlAnyElement
,
以便JAXB将其用于编组/解组。
但你想要一个Map<String, String>
。因此你也宣布了,
但注释为@XmlTransient
,以便JAXB不会将其用于编组/解组。
最后实现私有方法afterUnmarshal(Unmarshaller unmarshaller, Object parent)
您将内容从List<Element>
铲到Map<String, String>
。
如中所述
docs
JAXB将在适当的时候调用此方法。
如果您需要编写XML文件
您可能还需要私有方法beforeMmarshal(Marshaller marshaller)
将内容从Map<String, String>
铲回List<Element>
。
如中所述
Unmarshal Event Callbacks
JAXB将在适当的时候调用此方法。
public class Item {
@XmlElement
private String id;
@XmlElement
private String type;
@XmlAnyElement
private List<Element> otherElements;
@XmlTransient // don't participate in JAXB marshalling/unmarshalling
private Map<String, String> values;
@SuppressWarnings("unused") // called only by JAXB
private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
values = new HashMap<>();
if (otherElements != null) {
for (Element element : otherElements) {
String key = element.getNodeName();
String value = element.getFirstChild().getNodeValue();
values.put(key, value);
}
}
}
}