我发现很多文章描述了如何将XML元素序列编组到HashMap,只要它们在“父”元素内。但是,我不希望它直接与root元素下的孩子一起工作!
选项1-运作:
<?xml version="1.0" encoding="UTF-8"?> <checks> <checks> <check key="check1"/> <check key="check2"/> ... </checks> </checks>
选项2 -难道 不 工作:
<?xml version="1.0" encoding="UTF-8"?> <checks> <check key="check1"/> <check key="check2"/> ... </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; }
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:
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:
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; } }
这是(一些虚拟测试行)我如何生成类/调用解组的方法:
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());
关于如何使选项2起作用的任何想法吗?当使用列表而不是Map时它可以工作,但是我需要HashMap,因为我必须通过给定的键来访问对象…
任何提示非常感谢!
注意: 我是 EclipseLink JAXB(MOXy)的 负责人,并且是 JAXB(JSR-222) 专家组的成员。
JAXB将使用嵌套关系来处理每个对象关系。 Map被视为Object而不是,Collection因此这就是为什么您得到所看到的行为的原因。
Map
Object
Collection
MOXy有一个称为XPath的基于映射的扩展名@XmlPath,可以用于此用例。
@XmlPath
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; }
想要查询更多的信息