JAXB 如何编组可选或可空的元素

Nev*_*ril 5 java xml jaxb

我正在尝试封送一个元素,该元素可以为 null,并且在某些情况下根本不应该写入最终的 XML,在其他一些情况下,我应该指定它可以为空。

考虑下面的例子

<root>
    <element>
        <sub1>Whatever1</sub1>
        <sub2 xsi:nil="true"/>
    </element>
    <element>
        <sub1>Whatever2</sub1>
        <sub2>Not empty</sub2>
    </element>
    <element>
        <sub1>Whatever3</sub1>
    </element>
</root>
Run Code Online (Sandbox Code Playgroud)

元素“sub2”是我遇到问题的元素。

根据我的理解,我可以使用 Element 类声明如下轻松实现前两种情况:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "element", propOrder = {
        "sub1",
        "sub2",
})
public class Element {

    @XmlElement(required = true)
    public String sub1;
    @XmlElement(nillable = true)
    public String sub2;
    //...
}
Run Code Online (Sandbox Code Playgroud)

为了获得最后两个,我会这样做:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "element", propOrder = {
        "sub1",
        "sub2",
})
public class Element {

    @XmlElement(required = true)
    public String sub1;
    @XmlElement(required = false) //I could omit it entirely
    public String sub2;
    //...
}
Run Code Online (Sandbox Code Playgroud)

有没有办法同时获得?

我被迫使用 Java 6 / JAXB 2.1.10。

谢谢你。

Jes*_*per 4

是的,可以有既不是必需的又可以为空的元素。为了使这项工作顺利进行,您需要做一些事情:

  1. 将字段设为 aJAXBElement<String>而不是String
  2. ObjectFactory使用工厂方法创建一个类。
  3. @XmlElementDecl工厂方法放在ObjectFactory@XmlElementRef类的字段中Element

例子:

使字段aJAXBElement<String>带有@XmlElementRef注释:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "element", propOrder = {"sub1", "sub2"})
@XmlRootElement
public class Element {

    @XmlElement(required = true)
    public String sub1;

    @XmlElementRef(name = "sub2", required = false)
    public JAXBElement<String> sub2;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

创建一个ObjectFactory带有工厂方法和@XmlElementDecl注释的类。@XmlElementRef请注意,和注释的命名空间和名称@XmlElementDecl是相同的:

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name = "sub2")
    public JAXBElement<String> createSub2(String value) {
        return new JAXBElement<>(new QName(null, "sub2"),
                                 String.class, Element.class, value);
    }
}
Run Code Online (Sandbox Code Playgroud)

编组示例 1: 具有以下值sub2

ObjectFactory objectFactory = new ObjectFactory();

Element element = new Element();
element.setSub1("one");
element.setSub2(objectFactory.createSub2("two"));

JAXBContext context = JAXBContext.newInstance(ObjectFactory.class, Element.class);

Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(element, System.out);
Run Code Online (Sandbox Code Playgroud)

输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<element>
    <sub1>one</sub1>
    <sub2>two</sub2>
</element>
Run Code Online (Sandbox Code Playgroud)

编组示例 2:XML 中根本没有元素:

Element element = new Element();
element.setSub1("one");
// Leave the field sub2 set to null
Run Code Online (Sandbox Code Playgroud)

输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<element>
    <sub1>one</sub1>
</element>
Run Code Online (Sandbox Code Playgroud)

编组示例 3:创建一个元素,其值null将显示为 XML 元素,设置为nil

Element element = new Element();
element.setSub1("one");
element.setSub2(objectFactory.createSub2(null));
Run Code Online (Sandbox Code Playgroud)

输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<element>
    <sub1>one</sub1>
    <sub2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</element>
Run Code Online (Sandbox Code Playgroud)