繁体   English   中英

JAXB将XML元素解组到HashMap

[英]JAXB unmarshal XML elements to HashMap

我发现了很多文章,描述了如何将一系列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因此这就是为什么您得到所看到的行为的原因。

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;     
}

欲获得更多信息

您如何生成JAXB类? 我不确定您到底想做什么,但是下面的简单代码对我有用。

    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);
    }

这是我的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;
        }

   }

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM