[英]JAXB unmarshal XML elements to HashMap
I found a lot of articles that describe how to unmarshal a sequence of XML elements to a HashMap as long as they are within a "parent" element. 我发现了很多文章,描述了如何将一系列XML元素解组到HashMap,只要它们位于“父”元素中。 However, I do not get this to work with the children directly under the root element!
但是,我不希望它直接与root元素下的孩子一起工作!
Option 1 - Works: 选项1-运作:
<?xml version="1.0" encoding="UTF-8"?>
<checks>
<checks>
<check key="check1"/>
<check key="check2"/>
...
</checks>
</checks>
Option 2 - Does not work: 选项2 - 不工作:
<?xml version="1.0" encoding="UTF-8"?>
<checks>
<check key="check1"/>
<check key="check2"/>
...
</checks>
Checks: 检查:
package com.foo.conf;
import java.util.Map;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name="checks")
public class Checks {
@XmlJavaTypeAdapter(ChecksAdapter.class)
@XmlElement(name="checks")
public Map<String, Check> checkMap;
}
Check: 校验:
package com.foo.conf;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlValue;
public class Check {
@XmlAttribute public String key;
@XmlValue public String description;
public Check() { }
public Check(String key) {
this.key = key;
}
public String getCheckKey() {
return this.key;
}
}
CheckMapType: CheckMapType:
package com.foo.conf;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
class CheckMapType {
@XmlElement(name="check")
public List<Check> checkList; // = new ArrayList<Check>();
}
ChecksAdapter: ChecksAdapter:
package com.foo.conf;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.adapters.XmlAdapter;
final class ChecksAdapter extends XmlAdapter<CheckMapType, Map<String, Check>> {
@Override
public CheckMapType marshal(Map<String, Check> arg0) throws Exception {
return null;
}
@Override
public Map<String, Check> unmarshal(CheckMapType arg0) throws Exception {
System.out.println("u: " + arg0.checkList.size());
Map<String, Check> map = new HashMap<String, Check>();
for (Check check : arg0.checkList) {
System.out.println(check);
map.put(check.key, check);
}
return map;
}
}
This is (some dummy test lineS) how I generate the classes/invoke the unmarshalling: 这是(一些虚拟测试行)我生成类/调用解组的方式:
JAXBContext jc = JAXBContext.newInstance(Checks.class);
Unmarshaller u = jc.createUnmarshaller();
Checks c = (Checks) u.unmarshal(new File("checks.xml"));
System.out.println(c.checkMap.size());
Any idea on how to get option #2 to work? 关于如何使选项2起作用的任何想法吗? It works when using a List instead of the Map but I need the HashMap as I have to access the objects by the given keys...
当使用列表而不是Map时它可以工作,但是我需要HashMap,因为我必须通过给定的键来访问对象...
Any hints much appreciated! 任何提示非常感谢!
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group. 注意:我是EclipseLink JAXB(MOXy)的负责人,并且是JAXB(JSR-222)专家组的成员。
JAXB will treat each object relationship with a nesting relationship. JAXB将使用嵌套关系对待每个对象关系。
Map
is treated like an Object
instead of a Collection
so this is why you are getting the behaviour that you are seeing. Map
被视为Object
而不是Collection
因此这就是为什么您得到所看到的行为的原因。
MOXy has an XPath based mapping extension called @XmlPath
that could be used for this use case. MOXy有一个名为
@XmlPath
基于XPath的映射扩展,可以用于此用例。
package com.foo.conf;
import java.util.Map;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement(name="checks")
public class Checks {
@XmlJavaTypeAdapter(ChecksAdapter.class)
@XmlPath(".")
public Map<String, Check> checkMap;
}
For More Information 欲获得更多信息
How are you generaing the JAXB classes? 您如何生成JAXB类? I am not sure what exactly are you trying to do but the below very simple code works for me ..
我不确定您到底想做什么,但是下面的简单代码对我有用。
JAXBContext jc = JAXBContext.newInstance(ChecksType.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
ChecksType chksType = (ChecksType) unmarshaller.unmarshal(new File("/path/to/xml"));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(chksType, System.out);
System.err.println(chksType.getCheck().get(0).getKey());
for (CheckType checkType : chksType.getCheck()) {
System.out.println("key = " + checkType.getKey() + ", " + checkType);
}
and here is my JAXB generated classes .. ChecksType
(Root element) 这是我的JAXB生成的类..
ChecksType
(根元素)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "checksType", propOrder = { "check" })
@XmlRootElement(name = "checks")
public class ChecksType {
@XmlElement(required = true)
protected List<CheckType> check;
public List<CheckType> getCheck() {
if (check == null) {
check = new ArrayList<CheckType>();
}
return this.check;
}
}
And checkType
(the child) 和
checkType
(孩子)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "checkType")
public class CheckType {
@XmlAttribute(name = "key")
protected String key;
public String getKey() {
return key;
}
public void setKey(String value) {
this.key = value;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.