Java JAXB:如何将映射到<;键>;价值</键>;
问题是关于JAXB映射编组的——有很多关于如何将映射编组为如下结构的示例:Java JAXB:如何将映射到<;键>;价值</键>;,java,xml,jaxb,jaxb2,Java,Xml,Jaxb,Jaxb2,问题是关于JAXB映射编组的——有很多关于如何将映射编组为如下结构的示例: <map> <entry> <key> KEY </key> <value> VALUE </value> </entry> <entry> <key> KEY2 </key> <value> VALUE2 </value> <
<map>
<entry>
<key> KEY </key>
<value> VALUE </value>
</entry>
<entry>
<key> KEY2 </key>
<value> VALUE2 </value>
</entry>
<entry>
...
</map>
钥匙
价值
键2
价值2
...
事实上,这是JAXB本机支持的。但是,我需要的是XML,其中key是元素名,value是其内容:
<map>
<key> VALUE </key>
<key2> VALUE2 </key2>
...
</map>
价值
价值2
...
我没有按照JAXB开发人员()推荐的方式成功地实现映射适配器,正如我所需要的那样,he-dynamic attribute name:)
有什么解决办法吗
另外,目前我必须为每一组典型的键值对创建一个专用的容器类,我想将其转换为XML—这是可行的,但我必须创建太多的帮助器容器。我仍在研究一个更好的解决方案,但通过使用,我已经能够处理以下XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<mapProperty>
<map>
<key>value</key>
<key2>value2</key2>
</map>
</mapProperty>
</root>
此解决方案需要MOXy-JAXB实现。您可以通过在模型类中添加名为JAXB.properties的文件来配置JAXB运行时以使用MOXy实现,其中包含以下条目:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
以下演示代码可用于验证代码:
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(new File("src/forum74/input.xml"));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
提供的代码对我不起作用。 我找到了另一种绘制地图的方法: 地图元素:
package com.cellfish.mediadb.rest.lucene;
import javax.xml.bind.annotation.XmlElement;
class MapElements
{
@XmlElement public String key;
@XmlElement public Integer value;
private MapElements() {} //Required by JAXB
public MapElements(String key, Integer value)
{
this.key = key;
this.value = value;
}
}
映射适配器:
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.adapters.XmlAdapter;
class MapAdapter extends XmlAdapter<MapElements[], Map<String, Integer>> {
public MapElements[] marshal(Map<String, Integer> arg0) throws Exception {
MapElements[] mapElements = new MapElements[arg0.size()];
int i = 0;
for (Map.Entry<String, Integer> entry : arg0.entrySet())
mapElements[i++] = new MapElements(entry.getKey(), entry.getValue());
return mapElements;
}
public Map<String, Integer> unmarshal(MapElements[] arg0) throws Exception {
Map<String, Integer> r = new HashMap<String, Integer>();
for (MapElements mapelement : arg0)
r.put(mapelement.key, mapelement.value);
return r;
}
}
import java.util.HashMap;
导入java.util.Map;
导入javax.xml.bind.annotation.adapters.XmlAdapter;
类MapAdapter扩展了XmlAdapter{
公共MapElements[]封送处理(映射arg0)引发异常{
MapElements[]MapElements=新的MapElements[arg0.size()];
int i=0;
对于(Map.Entry:arg0.entrySet())
mapElements[i++]=新的mapElements(entry.getKey(),entry.getValue());
返回映射元素;
}
公共映射解组器(MapElements[]arg0)引发异常{
Map r=新的HashMap();
对于(MapElements mapelement:arg0)
r、 put(mapelement.key、mapelement.value);
返回r;
}
}
根元素:
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
public class Root {
private Map<String, Integer> mapProperty;
public Root() {
mapProperty = new HashMap<String, Integer>();
}
@XmlJavaTypeAdapter(MapAdapter.class)
public Map<String, Integer> getMapProperty() {
return mapProperty;
}
public void setMapProperty(Map<String, Integer> map) {
this.mapProperty = map;
}
}
import java.util.HashMap;
导入java.util.Map;
导入javax.xml.bind.annotation.XmlRootElement;
导入javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
公共类根{
私有地图财产;
公共根(){
mapProperty=newHashMap();
}
@XmlJavaTypeAdapter(MapAdapter.class)
公共映射getMapProperty(){
归还财产;
}
公共void setMapProperty(映射){
this.mapProperty=map;
}
}
我在这个网站上找到了代码:
这样做可能有一个合理的原因,但通常最好避免生成这种XML。为什么?因为这意味着地图的XML元素依赖于地图的运行时内容。而且,由于XML通常被用作外部接口或接口层,这是不可取的。让我解释一下 Xml模式(xsd)定义Xml文档的接口约定。除了能够从XSD生成代码外,JAXB还可以从代码中为您生成XML模式。这允许您将通过接口交换的数据限制为XSD中定义的预先约定的结构 在
Map
的默认情况下,生成的XSD将限制Map元素包含多个条目元素,每个条目元素必须包含一个xs:string
键和一个xs:string
值。这是一个非常明确的接口合同
您描述的是希望xml映射包含的元素的名称将由运行时映射的内容决定。然后,生成的XSD只能指定映射必须包含在编译时类型未知的元素列表。这是在定义接口契约时通常应该避免的事情
在这种情况下,要实现严格的约定,应该使用枚举类型作为映射的键,而不是字符串。例如
public enum KeyType {
KEY, KEY2;
}
@XmlJavaTypeAdapter(MapAdapter.class)
Map<KeyType , String> mapProperty;
公共枚举密钥类型{
键,键2;
}
@XmlJavaTypeAdapter(MapAdapter.class)
地图属性;
这样,您希望成为XML中元素的键在编译时就已经知道了,因此JAXB应该能够生成一个模式,使用预定义的键KEY或KEY2将map的元素限制为元素
另一方面,如果希望简化默认生成的结构
<map>
<entry>
<key>KEY</key>
<value>VALUE</value>
</entry>
<entry>
<key>KEY2</key>
<value>VALUE2</value>
</entry>
</map>
钥匙
价值
键2
价值2
到像这样简单的地方
<map>
<item key="KEY" value="VALUE"/>
<item key="KEY2" value="VALUE2"/>
</map>
可以使用MapAdapter将地图转换为MapElements数组,如下所示:
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class MapAdapter extends XmlAdapter<AdaptedMap, Map<String, String>> {
@Override
public AdaptedMap marshal(Map<String, String> map) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
Element rootElement = document.createElement("map");
document.appendChild(rootElement);
for(Entry<String,String> entry : map.entrySet()) {
Element mapElement = document.createElement(entry.getKey());
mapElement.setTextContent(entry.getValue());
rootElement.appendChild(mapElement);
}
AdaptedMap adaptedMap = new AdaptedMap();
adaptedMap.setValue(document);
return adaptedMap;
}
@Override
public Map<String, String> unmarshal(AdaptedMap adaptedMap) throws Exception {
Map<String, String> map = new HashMap<String, String>();
Element rootElement = (Element) adaptedMap.getValue();
NodeList childNodes = rootElement.getChildNodes();
for(int x=0,size=childNodes.getLength(); x<size; x++) {
Node childNode = childNodes.item(x);
if(childNode.getNodeType() == Node.ELEMENT_NODE) {
map.put(childNode.getLocalName(), childNode.getTextContent());
}
}
return map;
}
}
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;
}
}
类映射元素{
@XmlAttribute
公共字符串密钥;
@XmlAttribute
公共字符串值;
私有映射元素(){
}//JAXB需要
公共映射元素(字符串键、字符串值){
this.key=key;
这个值=值;
}
}
公共类MapAdapter扩展了XmlAdapter{
公共映射适配器(){
}
公共MapElements[]封送处理(映射arg0)引发异常{
MapElements[]MapElements=新的MapElements[arg0.size()];
int i=0;
对于(Map.Entry:arg0.entrySet())
mapElements[i++]=新的mapElements(entry.getKey(),entry.getValue());
返回映射元素;
}
公共映射解组器(MapElements[]arg0)引发异常{
Map r=新树映射();
对于(MapElements mapelement:arg0)
r、 put(mapelement.key、mapelement.value);
返回r;
}
}
我有没有适配器的解决方案。转换为xml元素的瞬态映射,反之亦然:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "SchemaBasedProperties")
public class SchemaBasedProperties
{
@XmlTransient
Map<String, Map<String, String>> properties;
@XmlAnyElement(lax = true)
List<Object> xmlmap;
public Map<String, Map<String, String>> getProperties()
{
if (properties == null)
properties = new LinkedHashMap<String, Map<String, String>>(); // I want same order
return properties;
}
boolean beforeMarshal(Marshaller m)
{
try
{
if (properties != null && !properties.isEmpty())
{
if (xmlmap == null)
xmlmap = new ArrayList<Object>();
else
xmlmap.clear();
javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance();
javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
org.w3c.dom.Document doc = db.newDocument();
org.w3c.dom.Element element;
Map<String, String> attrs;
for (Map.Entry<String, Map<String, String>> it: properties.entrySet())
{
element = doc.createElement(it.getKey());
attrs = it.getValue();
if (attrs != null)
for (Map.Entry<String, String> at: attrs.entrySet())
element.setAttribute(at.getKey(), at.getValue());
xmlmap.add(element);
}
}
else
xmlmap = null;
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
void afterUnmarshal(Unmarshaller u, Object p)
{
org.w3c.dom.Node node;
org.w3c.dom.NamedNodeMap nodeMap;
String name;
Map<String, String> attrs;
getProperties().clear();
if (xmlmap != null)
for (Object xmlNode: xmlmap)
if (xmlNode instanceof org.w3c.dom.Node)
{
node = (org.w3c.dom.Node) xmlNode;
nodeMap = node.getAttributes();
name = node.getLocalName();
attrs = new HashMap<String, String>();
for (int i = 0, l = nodeMap.getLength(); i < l; i++)
{
node = nodeMap.item(i);
attrs.put(node.getNodeName(), node.getNodeValue());
}
getProperties().put(name, attrs);
}
xmlmap = null;
}
public static void main(String[] args)
throws Exception
{
SchemaBasedProperties props = new SchemaBasedProperties();
Map<String, String> attrs;
attrs = new HashMap<String, String>();
attrs.put("ResId", "A_LABEL");
props.getProperties().put("LABEL", attrs);
attrs = new HashMap<String, String>();
attrs.put("ResId", "A_TOOLTIP");
props.getProperties().put("TOOLTIP", attrs);
attrs = new HashMap<String, String>();
attrs.put("Value", "hide");
props.getProperties().put("DISPLAYHINT", attrs);
javax.xml.bind.JAXBContext jc = javax.xml.bind.JAXBContext.newInstance(SchemaBasedProperties.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(props, new java.io.File("test.xml"));
Unmarshaller unmarshaller = jc.createUnmarshaller();
props = (SchemaBasedProperties) unmarshaller.unmarshal(new java.io.File("test.xml"));
System.out.println(props.getProperties());
}
}
@xmlacessortype(xmlacesstype.FIELD)
@XmlRootElement(name=“SchemaBasedProperties”)
公共类SchemaBaseProperties
{
@XmlTransient
地图属性;
@xmlanyement(lax=true)
列表xmlmap;
公共映射getProperties()
{
如果(属性==null)
properties=new LinkedHashMap();//我想要相同的顺序
返回属性
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;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "SchemaBasedProperties")
public class SchemaBasedProperties
{
@XmlTransient
Map<String, Map<String, String>> properties;
@XmlAnyElement(lax = true)
List<Object> xmlmap;
public Map<String, Map<String, String>> getProperties()
{
if (properties == null)
properties = new LinkedHashMap<String, Map<String, String>>(); // I want same order
return properties;
}
boolean beforeMarshal(Marshaller m)
{
try
{
if (properties != null && !properties.isEmpty())
{
if (xmlmap == null)
xmlmap = new ArrayList<Object>();
else
xmlmap.clear();
javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory.newInstance();
javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
org.w3c.dom.Document doc = db.newDocument();
org.w3c.dom.Element element;
Map<String, String> attrs;
for (Map.Entry<String, Map<String, String>> it: properties.entrySet())
{
element = doc.createElement(it.getKey());
attrs = it.getValue();
if (attrs != null)
for (Map.Entry<String, String> at: attrs.entrySet())
element.setAttribute(at.getKey(), at.getValue());
xmlmap.add(element);
}
}
else
xmlmap = null;
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
return true;
}
void afterUnmarshal(Unmarshaller u, Object p)
{
org.w3c.dom.Node node;
org.w3c.dom.NamedNodeMap nodeMap;
String name;
Map<String, String> attrs;
getProperties().clear();
if (xmlmap != null)
for (Object xmlNode: xmlmap)
if (xmlNode instanceof org.w3c.dom.Node)
{
node = (org.w3c.dom.Node) xmlNode;
nodeMap = node.getAttributes();
name = node.getLocalName();
attrs = new HashMap<String, String>();
for (int i = 0, l = nodeMap.getLength(); i < l; i++)
{
node = nodeMap.item(i);
attrs.put(node.getNodeName(), node.getNodeValue());
}
getProperties().put(name, attrs);
}
xmlmap = null;
}
public static void main(String[] args)
throws Exception
{
SchemaBasedProperties props = new SchemaBasedProperties();
Map<String, String> attrs;
attrs = new HashMap<String, String>();
attrs.put("ResId", "A_LABEL");
props.getProperties().put("LABEL", attrs);
attrs = new HashMap<String, String>();
attrs.put("ResId", "A_TOOLTIP");
props.getProperties().put("TOOLTIP", attrs);
attrs = new HashMap<String, String>();
attrs.put("Value", "hide");
props.getProperties().put("DISPLAYHINT", attrs);
javax.xml.bind.JAXBContext jc = javax.xml.bind.JAXBContext.newInstance(SchemaBasedProperties.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(props, new java.io.File("test.xml"));
Unmarshaller unmarshaller = jc.createUnmarshaller();
props = (SchemaBasedProperties) unmarshaller.unmarshal(new java.io.File("test.xml"));
System.out.println(props.getProperties());
}
}
<SchemaBasedProperties>
<LABEL ResId="A_LABEL"/>
<TOOLTIP ResId="A_TOOLTIP"/>
<DISPLAYHINT Value="hide"/>
</SchemaBasedProperties>
{LABEL={ResId=A_LABEL}, TOOLTIP={ResId=A_TOOLTIP}, DISPLAYHINT={Value=hide}}
@XmlJavaTypeAdapter(MapAdapter.class)
@XmlPath(".") // <<-- add this
public Map<String, String> getMapProperty() {
return mapProperty;
}
<?xml version="1.0" encoding="UTF-8"?>
<root>
<map>
<key>value</key>
<key2>value2</key2>
</map>
</root>
@XmlJavaTypeAdapter(MapAdapter.class)
@XmlAnyElement // <<-- add this
public Map<String, String> getMapProperty() {
return mapProperty;
}
@XmlElement(name="attribute")
public String[] getAttributes(){
return attributes.keySet().toArray(new String[1]);
}
}
<attribute>key1<attribute>
...
<attribute>keyN<attribute>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<map>
<key>value</key>
<key2>value2</key2>
</map>
</root>
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@XmlRootElement
class Root {
public XmlRawData map;
}
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(new File("src/input.xml"));
System.out.println(root.map.getAsMap());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
class XmlRawData {
@XmlAnyElement
public List<Element> elements;
public void setFromMap(Map<String, String> values) {
Document document;
try {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
}
for (Entry<String, String> entry : values.entrySet()) {
Element mapElement = document.createElement(entry.getKey());
mapElement.appendChild(document.createTextNode(entry.getValue()));
elements.add(mapElement);
}
}
public Map<String, String> getAsMap() {
Map<String, String> map = new HashMap<String, String>();
for (Element element : elements) {
if (element.getNodeType() == Node.ELEMENT_NODE) {
map.put(element.getLocalName(), element.getFirstChild().getNodeValue());
}
}
return map;
}
}
public class MapAdapter extends XmlAdapter<MapWrapper, Map<String, Object>> {
@Override
public MapWrapper marshal(Map<String, Object> m) throws Exception {
MapWrapper wrapper = new MapWrapper();
List elements = new ArrayList();
for (Map.Entry<String, Object> property : m.entrySet()) {
if (property.getValue() instanceof Map)
elements.add(new JAXBElement<MapWrapper>(new QName(getCleanLabel(property.getKey())),
MapWrapper.class, marshal((Map) property.getValue())));
else
elements.add(new JAXBElement<String>(new QName(getCleanLabel(property.getKey())),
String.class, property.getValue().toString()));
}
wrapper.elements = elements;
return wrapper;
}
@Override
public Map<String, Object> unmarshal(MapWrapper v) throws Exception {
// TODO
throw new OperationNotSupportedException();
}
// Return a XML-safe attribute. Might want to add camel case support
private String getCleanLabel(String attributeLabel) {
attributeLabel = attributeLabel.replaceAll("[()]", "").replaceAll("[^\\w\\s]", "_").replaceAll(" ", "_");
return attributeLabel;
}
}
class MapWrapper {
@XmlAnyElement
List elements;
}
static class myxml {
String name = "Full Name";
String address = "1234 Main St";
// I assign values to the map elsewhere, but it's just a simple
// hashmap with a hashmap child as an example.
@XmlJavaTypeAdapter(MapAdapter.class)
public Map<String, Object> childMap;
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<myxml>
<name>Full Name</name>
<address>1234 Main St</address>
<childMap>
<key2>value2</key2>
<key1>value1</key1>
<childTree>
<childkey1>childvalue1</childkey1>
</childTree>
</childMap>
</myxml>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.8</version>
</dependency>
Map<String, String> map = new HashMap<>();
map.put("SomeKey", "someValue");
XmlMapper mapper = new XmlMapper();
String xml = mapper.writeValueAsString(map);
<HashMap><SomeKey>someValue</SomeKey></HashMap>
@JacksonXmlRootElement(localName = "MyRootElement")
public class XmlHashMap<K, V> extends HashMap<K, V>
{
}
Map<String, String> map = new XmlHashMap<>();
map.put("SomeKey", "someValue");
XmlMapper mapper = new XmlMapper();
String xml = mapper.writeValueAsString(map);
<MyRootElement><SomeKey>someValue</SomeKey></MyRootElement>
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.annotation.XmlAnyElement;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.xml.namespace.QName;
import lombok.Getter;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class MoxyMapAdapter extends XmlAdapter<MapWrapper, Map<String, Object>> {
@Override
public Map<String, Object> unmarshal(MapWrapper value) {
final Map<String, Object> extensions = new HashMap<>();
//Loop across all elements within value
for (Object obj : value.getElements()) {
Element element = (Element) obj;
final NodeList children = element.getChildNodes();
if (children.getLength() == 1) {
extensions.put(element.getNodeName(), element.getTextContent());
} else {
List<Object> child = new ArrayList<>();
for (int i = 0; i < children.getLength(); i++) {
final Node n = children.item(i);
if (n.getNodeType() == Node.ELEMENT_NODE) {
MapWrapper wrapper = new MapWrapper();
List childElements = new ArrayList();
childElements.add(n);
wrapper.elements = childElements;
child.add(unmarshal(wrapper));
}
}
extensions.put(element.getNodeName(), child);
}
}
return extensions;
}
@Override
public MapWrapper marshal(Map<String, Object> extensions) throws Exception {
if (extensions == null) {
return null;
}
MapWrapper wrapper = new MapWrapper();
List elements = new ArrayList();
//Loop through the Extensions MAP
for (Map.Entry<String, Object> property : extensions.entrySet()) {
//If the Value type is MAP then recurse through the loop
if (property.getValue() instanceof Map) {
elements
.add(new JAXBElement<MapWrapper>(new QName(namespaceURI, localPart, prefix), MapWrapper.class, marshal((Map) property.getValue())));
} else if (property.getValue() instanceof String) {
// If the Value type is String then directly create JAXBElement
elements.add(new JAXBElement<String>(new QName(namespaceURI, localPart, prefix), String.class, property.getValue().toString()));
} else if (property.getValue() instanceof ArrayList) {
//If the Value type is ArrayList then it contains Duplicate key values so Loop through it
for (Object dupItems : (ArrayList<String>) property.getValue()) {
if (dupItems instanceof Map) {
elements.add(new JAXBElement<MapWrapper>(new QName(namespaceURI, localPart, prefix), MapWrapper.class, marshal((Map) dupItems)));
} else {
elements.add(new JAXBElement<String>(new QName(namespaceURI, localPart, prefix), String.class, dupItems.toString()));
}
}
}
}
wrapper.elements = elements;
return wrapper;
}
}
class MapWrapper {
@Getter
@XmlAnyElement
List elements;
}