簡體   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