JAXB:如何在使用XmlJavaTypeAdapter时抑制周围的XmlElement? [英] JAXB: How to suppress surrounding XmlElement when using XmlJavaTypeAdapter?

查看:113
本文介绍了JAXB:如何在使用XmlJavaTypeAdapter时抑制周围的XmlElement?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 @XmlJavaTypeAdapter Map< String,MapItem> 对象转换为 List< ;编组时的MapItem> (当解组时反之亦然。)

I use @XmlJavaTypeAdapter to transform Map<String, MapItem> objects into List<MapItem> when marshalling (and vice versa when unmarshalling.)

列表总是有一个 @XmlElement 我希望摆脱它,因为它使得到的XML变得混乱。

The list always has a surrounding @XmlElement and I want to get rid of it as it clutters the resulting XML.

如何做到这一点?

或者换句话说,如何在以下XML中删除元素 map

Or, in other words, how can I get rid of element map in the following XML:

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



Class MapItem 是一个带键和值的简单类:


Class MapItemis a simple class with a key and a value:

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

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



声明 Map< String,MapItem> 隐式或显式包含 @XmlElement 注释:


The declaration of Map<String, MapItem> either implicitly or explicitly contains an @XmlElement annotation:

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



顶级声明:


The top class declaration:

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



我的完整测试类:


My complete test class:

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


推荐答案

注意:我是 EclipseLink JAXB(MOXy) 领导和 JAXB(JSR-222)的成员) 专家组。

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

您可以使用 @XmlPath(。)在MOXy中扩展以映射此用例。指定,因为路径指示应将子项的内容写入父对象元素。

You could use the @XmlPath(".") extension in MOXy to map this use case. Specifying "." as the path indicates that the contents of the child should be written into the parent objects element.

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

}

完整示例

  • JAXB marshal an ArrayList created by XmlAdapter

更多信息

  • http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
  • http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html

这篇关于JAXB:如何在使用XmlJavaTypeAdapter时抑制周围的XmlElement?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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