JAXB将XML元素解组为HashMap [英] JAXB unmarshal XML elements to HashMap

查看:563
本文介绍了JAXB将XML元素解组为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;
}

更多信息




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

这篇关于JAXB将XML元素解组为HashMap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆