JAXB:如何在使用XmlJavaTypeAdapter时抑制周围的XmlElement? [英] JAXB: How to suppress surrounding XmlElement when using XmlJavaTypeAdapter?
问题描述
我使用 @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
MapItem
is 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
- 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屋!