java - JAXB 删除不必要的嵌套 XML 标记

标签 java xml jakarta-ee jaxb javax.xml

目前我的程序有以下输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<container>
    <elements>
        <property name="e1">
            <foo name="Alex" status="Married"/>
        </property>
        <property name="e2">
            <foo name="Chris" status="Married with 2 children"/>
        </property>
    </elements>
</container>

如您所见,同时拥有 <container><elements>标签是没有用的。我想删除<elements> ,因此输出如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<container>
    <property name="e1">
        <foo name="Alex" status="Married"/>
    </property>
    <property name="e2">
        <foo name="Chris" status="Married with 2 children"/>
    </property>
</container>

下面列出了生成第一个输出的代码:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Container {

    @XmlElement
    @XmlJavaTypeAdapter(MyAdapter.class)
    private Map<String, Foo> elements = new HashMap<String, Foo>();

    public Container() {
        this.elements = new HashMap<String, Foo>();
    }

    public Map<String, Foo> getElements() {
        return elements;
    }

    @XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
    @XmlRootElement(name = "foo")
    static class Foo {
        @XmlAttribute
        public String name;

        @XmlAttribute
        public String status;

        public Foo(String name, String status) {
            this.name = name;
            this.status = status;
        }

        public Foo() {
        }
    }

    public static void main(String[] args) throws JAXBException {
        final JAXBContext context = JAXBContext.newInstance(Container.class);
        final Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        final Container c = new Container();
        final Map<String, Foo> elementsMap = c.getElements();
        elementsMap.put("e1", new Foo("Alex", "Married"));
        elementsMap.put("e2", new Foo("Chris", "Married with 2 children"));

        m.marshal(c, System.out);
    }
}

MyAdapter类,基于JAXB @XmlAdapter: Map -> List adapter? (marshall only) :

public class MyAdapter extends XmlAdapter<MyAdapter.AdaptedFoo, Map<String, Foo>> {

    static class AdaptedFoo {
        public List<Property> property = new ArrayList<>();
    }

    public static class Property {
        @XmlAttribute
        public String name;

        @XmlElementRef(type = Foo.class)
        public Foo value;
    }

    @Override
    public Map<String, Foo> unmarshal(AdaptedFoo v) throws Exception {
        return null;
    }

    @Override
    public AdaptedFoo marshal(Map<String, Foo> map) throws Exception {
        if (null == map) {
            return null;
        }
        AdaptedFoo adaptedFoo = new AdaptedFoo();
        for (Entry<String, Foo> entry : map.entrySet()) {
            Property property = new Property();
            property.name = entry.getKey();
            property.value = entry.getValue();
            adaptedFoo.property.add(property);
        }
        return adaptedFoo;
    }
}

如何删除 <elements>我的输出中的标签?

<小时/>

编辑:我找到了“肮脏”的方法 - 设置 @XmlRootElement(name = "")对于 Container类。但有什么“优雅”的方式吗?

最佳答案

XML 元素 <elements>需要将封闭的元素序列与属性 Map<?,?> elements 相关联。你不能丢弃它:解码器如何知道 <property> 在哪里?元素属于*元素 <container> 的级别.

拥有 List<Property>是不同的,因为 JAXB 将重复元素 x“硬连线”处理为 List<?> x ,所以不需要包装器。

由于您使用注释编写 Java 类,因此您可以通过添加(到容器)另一个“虚拟”字段并修改一些注释来使用它:

@XmlAccessorType(XmlAccessType.PROPERTY)
public class Container {
// ...
@XmlTransient    
public Map<String,Foo> getElements(){
    return elements;
}
private List<Property> property;
@XMLElement
public List<Property> getProperty(){
    List<Property>  props = elements.entrySet().stream()
                            .map( e -> new Property( e.getKey(), e.getValue() )
                            .collect( Collectors.toList() );
    return props;
}

较旧的 Java 可能会这样做

   List<Property> props = new ArrayList<>();
   for( Map.Entry<String,Foo> e: elements.entrySet() ){
       props.add( new Property( e.getKey(), e.getValue() ) );
   }
   return props;

这个编码是这样的:

<container>
    <property name="aaa">
       <foo name="aaaname" status="aaastatus"/>
    </property>
    <property name="bbb">
       <foo name="bbbname" status="bbbstatus"/>
    </property>
</container>

它不会解码!

关于java - JAXB 删除不必要的嵌套 XML 标记,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25246493/

相关文章:

java - 为什么编译器没有给出这个加法操作的错误?

xml - xpath - 具有属性问题的谓词

java - Glassfish JDBC : Do I have to use only jdbc/__default?

java - 我应该使用什么样的数据结构来处理海量数据

java - setter/getter 是否违反得墨忒耳法则?

java - DTO 应该包含不同的构造函数吗?

java - 为什么覆盖 onCreate(Bundle, PersistableBundle) 不起作用?

Android 开关 - 在开/关时更改开关的背景

javascript - 谷歌表格 xml 出现问题

java - 在 JMS 中使用 bytemessage 代替 objectMessage