【问题标题】:JAXB: How to suppress surrounding XmlElement when using XmlJavaTypeAdapter?JAXB:使用 XmlJavaTypeAdapter 时如何抑制周围的 XmlElement?
【发布时间】:2012-11-02 10:11:17
【问题描述】:

我在编组时使用@XmlJavaTypeAdapterMap<String, MapItem> 对象转换为List<MapItem>(反之亦然)。

列表周围总是有一个@XmlElement,我想去掉它,因为它会使生成的 XML 变得混乱。

如何做到这一点?

或者,换句话说,我怎样才能摆脱以下 XML 中的元素 map

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<top>
    <map>
        <item val="some-val" key="some-key"/>
    </map>
</top>


MapItem 类是一个带有键和值的简单类:
public static class MapItem {
    @XmlAttribute(name = "key")
    String key;

    @XmlAttribute(name = "val")
    String val;
}


Map&lt;String, MapItem&gt; 的声明隐式或显式包含 @XmlElement 注释:
@XmlJavaTypeAdapter(MyMapItemAdapter.class)
@XmlElement(name = "map")
Map<String, MapItem> map = new TreeMap<String, MapItem>();


@XmlJavaTypeAdapter 的类:
@XmlType(name = "map-type", propOrder = { "list" })
static class MyMapItemType {
    @XmlElement(name = "item")
    List<MapItem> list = new ArrayList<MapItem>();
}

@XmlTransient
static final class MyMapItemAdapter extends
        XmlAdapter<MyMapItemType, Map<String, MapItem>> {

    MyMapItemAdapter() {
    }

    @Override
    public MyMapItemType marshal(Map<String, MapItem> arg0)
            throws Exception {
        MyMapItemType myMapType = new MyMapItemType();
        for (Entry<String, MapItem> entry : arg0.entrySet()) {
            myMapType.list.add(entry.getValue());
        }
        return myMapType;
    }

    @Override
    public Map<String, MapItem> unmarshal(MyMapItemType arg0)
            throws Exception {
        TreeMap<String, MapItem> treeMap = new TreeMap<String, MapItem>();
        for (MapItem myEntryType : arg0.list) {
            treeMap.put(myEntryType.key, myEntryType);
        }
        return treeMap;
    }
}


顶级声明:
@XmlRootElement(name = "top")
@XmlType(name = "top")
@XmlAccessorType(XmlAccessType.FIELD)
public class JaxbMapTest {


我完整的测试课:
package xml;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement(name = "top")
@XmlType(name = "top")
@XmlAccessorType(XmlAccessType.FIELD)
public class JaxbMapTest {

    public static class MapItem {
        @XmlAttribute(name = "key")
        String key;

        @XmlAttribute(name = "val")
        String val;
    }

    @XmlTransient
    static final class MyMapItemAdapter extends
            XmlAdapter<MyMapItemType, Map<String, MapItem>> {

        MyMapItemAdapter() {
        }

        @Override
        public MyMapItemType marshal(Map<String, MapItem> arg0)
                throws Exception {
            MyMapItemType myMapType = new MyMapItemType();
            for (Entry<String, MapItem> entry : arg0.entrySet()) {
                myMapType.list.add(entry.getValue());
            }
            return myMapType;
        }

        @Override
        public Map<String, MapItem> unmarshal(MyMapItemType arg0)
                throws Exception {
            TreeMap<String, MapItem> treeMap = new TreeMap<String, MapItem>();
            for (MapItem myEntryType : arg0.list) {
                treeMap.put(myEntryType.key, myEntryType);
            }
            return treeMap;
        }
    }

    @XmlType(name = "map-type", propOrder = { "list" })
    static class MyMapItemType {
        @XmlElement(name = "item")
        List<MapItem> list = new ArrayList<MapItem>();
    }

    public static void main(String[] args) {

        try {

            // Setup object
            JaxbMapTest jaxbMapTest = new JaxbMapTest();
            MapItem mapItem = new MapItem();
            mapItem.key = "some-key";
            mapItem.val = "some-val";
            jaxbMapTest.add(mapItem);

            // Marshal
            JAXBContext jaxbContext = JAXBContext
                    .newInstance(JaxbMapTest.class);
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                    Boolean.TRUE);
            marshaller.marshal(jaxbMapTest, new File("JaxbMapTest.out"));

            // Exit
            System.exit(0);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    @XmlJavaTypeAdapter(MyMapItemAdapter.class)
    @XmlElement(name = "map")
    Map<String, MapItem> map = new TreeMap<String, MapItem>();

    void add(MapItem mapItem) {
        map.put(mapItem.key, mapItem);
    }
}

【问题讨论】:

    标签: xml jaxb suppress


    【解决方案1】:

    注意:我是EclipseLink JAXB (MOXy) 的负责人,也是JAXB (JSR-222) 专家组的成员。

    您可以使用 MOXy 中的 @XmlPath(".") 扩展来映射此用例。指定"."作为路径表示子元素的内容应该写入父对象元素。

    import java.util.HashMap;
    import javax.xml.bind.annotation.*;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    import org.eclipse.persistence.oxm.annotations.XmlPath;
    
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Foo {
    
        @XmlJavaTypeAdapter(MyMapItemAdapter.class)
        @XmlPath(".")
        Map<String, MapItem> map = new TreeMap<String, MapItem>();       
    
    }
    

    完整示例

    更多信息

    【讨论】:

    • 感谢您的建议,会记住的。没有什么反对 MOXy 的,但是有一个标准的解决方案会很好。我也考虑过使用Set&lt;MapItem&gt;(与HashSetTreeSet),但缺点是我必须为AbstractMap.get() 找到一个可维护的替代方案。 (顺便说一句,非常感谢您的帖子,我经常阅读,非常感谢!)
    • 感谢您的回复。但是如果有另一个@XmlElementMap,你会怎么做。这实际上导致了 b/w Adapter@XmlPath(".") 的冲突。我已经发布了与此相关的问题,您可以看看这个并提供一些解决方案或解决方法吗? stackoverflow.com/q/67860792/7584240
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    相关资源
    最近更新 更多