JAXB将XML元素解组为HashMap [英] JAXB unmarshal XML elements to HashMap
问题描述
我发现了很多描述如何将一系列XML元素解组到HashMap的文章,只要它们在父元素内。然而,我没有得到这与直接根源下的孩子们一起工作!
选项1 - 作品:
<?xml version =1.0encoding =UTF-8?>
<支票>
<支票>
< check key =check1/>
< check key =check2/>
...
< / checks>
< / checks>
选项2 - 没有 工作:
<?xml version =1.0encoding =UTF-8?>
<支票>
< 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;
$ b CheckMapType:
package com.foo.conf;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
class CheckMapType {
@XmlElement(name =check)
public List< Check>检查表; // = 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)抛出异常{
System.out.println(u:+ arg0.checkList.size());
地图< String,Check> map = new HashMap< String,Check>(); $(check check:arg0.checkList){
System.out.println(check);
map.put(check.key,check);
}
返回地图;
$ / code>
这是(一些虚拟测试线)我如何产生类/调用解组:
$ b JAXBContext jc = JAXBContext.newInstance(Checks.class);
Unmarshaller u = jc.createUnmarshaller();
支票c =(支票)u.unmarshal(新文件(checks.xml));
System.out.println(c.checkMap.size());
有关如何获得选项#2的任何想法?它使用List而不是Map来工作,但我需要HashMap,因为我必须通过给定的键来访问对象...
任何提示都非常感谢! / p>
解决方案 注意:我是 EclipseLink JAXB(MOXy) 负责人和 JAXB(JSR-222) 专家组。 JAXB将以嵌套关系来处理每个对象关系。 Map 被视为 Object
而不是集合
so这就是为什么你会看到你所看到的行为。
MOXy有一个基于XPath的映射扩展,名为 @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;
导入org.eclipse.persistence.oxm.annotations.XmlPath;
$ b $ @ @mlRootElement(name =checks)
public class Checks {
@XmlJavaTypeAdapter(ChecksAdapter.class)
@XmlPath(。)
public Map< String,Check> checkMap;
}
更多信息
- http ://blog.bdoughan.com/2010/07/xpath-based-mapping.html
- http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
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. However, I do not get this to work with the children directly under the root element!
Option 1 - Works:
<?xml version="1.0" encoding="UTF-8"?>
<checks>
<checks>
<check key="check1"/>
<check key="check2"/>
...
</checks>
</checks>
Option 2 - Does not work:
<?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:
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;
}
}
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? 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...
Any hints much appreciated!
解决方案 Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
JAXB will treat each object relationship with a nesting relationship. Map
is treated like an Object
instead of a Collection
so this is why you are getting the behaviour that you are seeing.
MOXy has an XPath based mapping extension called @XmlPath
that could be used for this use case.
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
- http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
- http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
这篇关于JAXB将XML元素解组为HashMap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!