我有一个XML文件。在此文件中,某些元素具有更改的属性。我想将这些属性放入Map中。我该怎么做?
我的XML是:
<ROW id='1'>
<MOBILE>9831138683</MOBILE>
<VARS>
<CAUSE>Delayed payment</CAUSE>
<DO>100.56</DO>
<LOT>1</LOT>
</VARS>
</ROW>
<ROW id='2'>
<MOBILE>9831138684</MOBILE>
<VARS>
<NAME>hi</NAME>
<ADDRESS>Here</ADDRESS>
<LOT>2</LOT>
</VARS>
</ROW>
在此,VARS
元素可以具有更改的属性,我事先不知道这些元素将是什么。
我为此创建了一个类:
@XmlRootElement(name = "ROW")
@XmlAccessorType(XmlAccessType.FIELD)
public class SMSDetail {
@XmlAttribute
private int id;
@XmlElement(name = "MOBILE")
private int mobileNo;
@XmlElement(name = "VARS")
@XmlJavaTypeAdapter(MapAdapter.class)
private HashMap<String, String> variableMap;
public int getId() {
return id;
}
public int getMobileNo() {
return mobileNo;
}
public HashMap<String, String> getVariableMap() {
return variableMap;
}
public void setId(int id) {
this.id = id;
}
public void setMobileNo(int mobileNo) {
this.mobileNo = mobileNo;
}
public void setVariableMap(HashMap<String, String> variableMap) {
this.variableMap = variableMap;
}
}
我想将VARS
元素映射到Map
。我希望CAUSE
,LOT
等标记为关键字,其值为地图中的值。我为此目的写了XmlAdapater
:
public class MapAdapter extends XmlAdapter<MapElements[], Map<String, String>> {
public MapAdapter() {
}
@Override
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;
}
@Override
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;
}
}
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;
}
}
此适配器为null
变量提供了variableMap
。应如何修改适配器?
答案 0 :(得分:11)
您可以执行以下操作:
MapAdapter
)您可以对XmlAdapter
执行以下操作,将Map
的实例转换为具有List
DOM Element
的对象。您将构造Element
的实例,以便名称是映射条目中的键,文本内容是值。
import java.util.*;
import java.util.Map.Entry;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
public class MapAdapter extends XmlAdapter<MapAdapter.AdaptedMap, Map<String, String>> {
private DocumentBuilder documentBuilder;
public MapAdapter() throws Exception {
documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
public static class AdaptedMap {
@XmlAnyElement
public List<Element> elements = new ArrayList<Element>();
}
@Override
public AdaptedMap marshal(Map<String, String> map) throws Exception {
Document document = documentBuilder.newDocument();
AdaptedMap adaptedMap = new AdaptedMap();
for(Entry<String, String> entry : map.entrySet()) {
Element element = document.createElement(entry.getKey());
element.setTextContent(entry.getValue());
adaptedMap.elements.add(element);
}
return adaptedMap;
}
@Override
public Map<String, String> unmarshal(AdaptedMap adaptedMap) throws Exception {
HashMap<String, String> map = new HashMap<String, String>();
for(Element element : adaptedMap.elements) {
map.put(element.getLocalName(), element.getTextContent());
}
return map;
}
}
MapAdapter
为了提高性能,我们希望尽量减少DocumentBuiderFactory
和DocumentBuilder
实例化的次数。我们可以通过为JAXB创建MapAdapter
的实例来实现此目的,并在Marshaller
和Unmarshaller
上进行设置。这样,JAXB将使用该实例,而不是每次需要适配器时都创建一个新实例。
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(SMSDetail.class);
MapAdapter mapAdapter = new MapAdapter();
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setAdapter(mapAdapter);
File xml = new File("src/forum27182975/input.xml");
SMSDetail smsDetail = (SMSDetail) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setAdapter(mapAdapter);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(smsDetail, System.out);
}
}
如果您使用MOXy作为JAXB提供程序,那么您可以利用@XmlVariableNode
扩展名来简化此用例的映射: