繁体   English   中英

JAXB解组XML到Map的元素

[英]JAXB unmarshal elements of XML to Map

我有一个XML文件。 在此文件中,某些元素具有更改的属性。 我想将这些属性放入Map中。 我该怎么做呢?

我的XML是:

<ROW id='1'>
    <MOBILE>9831138683</MOBILE>
    <VARS>
        <CAUSE>Delayed payment</CAUSE>
        <DO>100.56</DO>
        <LOT>1</LOT>
    </VARS>
</ROW>
<ROW id='2'>
    <MOBILE>9831138684</MOBILE>
    <VARS>
        <NAME>hi</NAME>
        <ADDRESS>Here</ADDRESS>
        <LOT>2</LOT>
    </VARS>
</ROW>

在这种情况下, VARS元素可以具有更改的属性,并且我事先不知道这些元素将是什么。

我为此创建了一个类:

@XmlRootElement(name = "ROW")
@XmlAccessorType(XmlAccessType.FIELD)
public class SMSDetail {
    @XmlAttribute
    private int id;
    @XmlElement(name = "MOBILE")
    private int mobileNo;
    @XmlElement(name = "VARS")
    @XmlJavaTypeAdapter(MapAdapter.class)
    private HashMap<String, String> variableMap;

    public int getId() {
        return id;
    }

    public int getMobileNo() {
        return mobileNo;
    }

    public HashMap<String, String> getVariableMap() {
        return variableMap;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setMobileNo(int mobileNo) {
        this.mobileNo = mobileNo;
    }

    public void setVariableMap(HashMap<String, String> variableMap) {
        this.variableMap = variableMap;
    }
}

我想将VARS元素映射到Map 我希望像CAUSELOT这样的标签是键,它们的值是地图中的值。 我为此编写了一个XmlAdapater

public class MapAdapter extends XmlAdapter<MapElements[], Map<String, String>> {
    public MapAdapter() {
    }

    @Override
    public MapElements[] marshal(Map<String, String> arg0) throws Exception {
        MapElements[] mapElements = new MapElements[arg0.size()];
        int i = 0;
        for (Map.Entry<String, String> entry : arg0.entrySet())
            mapElements[i++] = new MapElements(entry.getKey(), entry.getValue());

        return mapElements;
    }

    @Override
    public Map<String, String> unmarshal(MapElements[] arg0) throws Exception {
        Map<String, String> r = new TreeMap<String, String>();
        for (MapElements mapelement : arg0)
            r.put(mapelement.key, mapelement.value);
        return r;
    }
}

class MapElements {
    @XmlAttribute
    public String key;
    @XmlAttribute
    public String value;

    private MapElements() {
    } //Required by JAXB

    public MapElements(String key, String value) {
        this.key = key;
        this.value = value;
    }
}

这个适配器为variableMap变量赋予null 应该如何修改适配器?

您可以执行以下操作:

XmlAdapter( MapAdapter

您可以为XmlAdapter执行以下XmlAdapter ,将Map的实例转换为具有DOM Element List的对象。 您将构造Element的实例,以便名称是映射条目中的键,文本内容是值。

import java.util.*;
import java.util.Map.Entry;

import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.*;

public class MapAdapter extends XmlAdapter<MapAdapter.AdaptedMap, Map<String, String>> {

    private DocumentBuilder documentBuilder;

    public MapAdapter() throws Exception {
        documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    }

    public static class AdaptedMap {        
        @XmlAnyElement
        public List<Element> elements = new ArrayList<Element>();
    }

    @Override
    public AdaptedMap marshal(Map<String, String> map) throws Exception {
        Document document = documentBuilder.newDocument();
        AdaptedMap adaptedMap = new AdaptedMap();
        for(Entry<String, String> entry : map.entrySet()) {
            Element element = document.createElement(entry.getKey());
            element.setTextContent(entry.getValue());
            adaptedMap.elements.add(element);
        }
        return adaptedMap;
    }

    @Override
    public Map<String, String> unmarshal(AdaptedMap adaptedMap) throws Exception {
        HashMap<String, String> map = new HashMap<String, String>();
        for(Element element : adaptedMap.elements) {
            map.put(element.getLocalName(), element.getTextContent());
        }
        return map;
    }


}

优化MapAdapter的使用

为了提高性能,我们希望最小化DocumentBuiderFactoryDocumentBuilder实例化的次数。 我们可以通过创建MapAdapter for JAXB的实例来MapAdapter ,并在MarshallerUnmarshaller上设置它。 这样,JAXB将在每次需要适配器时使用该实例而不是创建新实例。

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(SMSDetail.class);

        MapAdapter mapAdapter = new MapAdapter();

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.setAdapter(mapAdapter);
        File xml = new File("src/forum27182975/input.xml");
        SMSDetail smsDetail = (SMSDetail) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setAdapter(mapAdapter);
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(smsDetail, System.out);
    }

}

如果您使用MOXy作为JAXB(JSR-222)提供程序

如果您使用MOXy作为JAXB提供程序,那么您可以利用@XmlVariableNode扩展来@XmlVariableNode此用例的映射:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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