java JAXB 将 XML 的元素解组为 Map
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27182975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JAXB unmarshal elements of XML to Map
提问by khateeb
I have an XML file. In this file, some of the elements are have attributes that change. I want to put those attributes into a Map. How do I do this?
我有一个 XML 文件。在此文件中,某些元素的属性会发生变化。我想将这些属性放入地图中。我该怎么做呢?
My XML is:
我的 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>
In this, the VARS
element can have attributes which changes and I do not know beforehand what these elements will be.
在这种情况下,VARS
元素可以具有更改的属性,我事先不知道这些元素将是什么。
I have created a class for this purpose:
为此,我创建了一个类:
@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;
}
}
I want to map the VARS
element to a Map
. I want the tags such as CAUSE
, LOT
to be keys and their values to be the values in the map. I have written an XmlAdapater
for this purpose:
我想将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;
}
}
This adapter is giving me null
for the variableMap
variable. How should the Adapter be modified for this?
该适配器是给我null
的variableMap
变量。为此应如何修改 Adapter?
回答by bdoughan
You could do the following:
您可以执行以下操作:
XmlAdapter (MapAdapter
)
XmlAdapter ( MapAdapter
)
You could do the following for your XmlAdapter
where you convert an instance of Map
to an object that has a List
of DOM Element
. You will construct the instances of Element
so that the name is they key from the map entry, and the text content is the value.
您可以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;
}
}
Optimizing the Use of MapAdapter
优化使用 MapAdapter
To improve performance we want to minimize the number of times the DocumentBuiderFactory
and DocumentBuilder
is instantiated. We can do this by creating an instance of the MapAdapter
for JAXB to use and set it on the Marshaller
and Unmarshaller
. This way JAXB will use that instance instead of creating a new one each time the adapter is required.
为了提高性能,我们希望最小化DocumentBuiderFactory
和DocumentBuilder
的实例化次数。我们可以通过创建一个MapAdapter
供 JAXB 使用的的实例并将其设置在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);
}
}
If You are Using MOXy as your JAXB (JSR-222) Provider
如果您使用 MOXy 作为 JAXB (JSR-222) 提供程序
If you are using MOXy as your JAXB provider then you can leverage the @XmlVariableNode
extension to make the mapping of this use case easier:
如果您使用 MOXy 作为您的 JAXB 提供程序,那么您可以利用该@XmlVariableNode
扩展来简化此用例的映射: