【问题标题】:JAXB generate nillable = "true" from javaJAXB 从 java 生成 nillable = "true"
【发布时间】:2013-11-19 15:50:51
【问题描述】:

这是一个错误吗?

我的 xsd 架构中需要 nillable = "true"。从我的java代码生成这样一个元素的唯一方法是使用@XmlElement(nillable = true),对吧?但是在这种情况下,我将无法利用这个定义,我将无法检查元素是否设置为nil。方法isNil()JAXBElement 包装类中。

那么,我的选择是什么 - 我想在我的 xsd 架构中生成 nillable = "true" 并能够检查它是否是从我的 java 代码中设置的。

【问题讨论】:

  • xs:nil=truenull 不一样吗?因此,如果您的元素在 xml 中设置为 nil,则您的字段在 java 中将为 null。

标签: java jaxb xml-nil jaxbelement


【解决方案1】:

我的 xsd 架构中需要 nillable = "true"。生成的唯一方法 我的 java 代码中的这样一个元素是使用 @XmlElement(nillable = 真的),对吧?

是的。

但在这种情况下,我将无法利用这一点 定义,我将无法检查元素是否设置为 nil。 方法 isNil() 在 JAXBElement 包装类中。

您可以执行getFoo() == null 来确定它是否为空。如果您试图确定 null 是否对应于不存在的元素或 xsi:nil="true",那么您将不得不做更多的事情。不会为缺少的节点设置集合,因此您可以将逻辑放入您的设置器中以跟踪是否由于具有 xsi:nil="true 的元素而设置为 null。

@XmlElement(nillable=true)
public String getFooString() {
    return fooString;
}

public void setFooString(String foo) {
    this.fooString = foo;
    this.setFoo = true;
}

如果您不想拥有这种额外的逻辑(无论如何这对编组没有帮助,您需要利用 JAXBElement

@XmlElementRef(name="fooJAXBElement")
public JAXBElement<String> getFooJAXBElement() {
    return fooJAXBElement;
}

public void setFooJAXBElement(JAXBElement<String> fooJAXBElement) {
    this.fooJAXBElement = fooJAXBElement;
}

Java 模型

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlType(propOrder={"fooString", "barString", "fooJAXBElement", "barJAXBElement"})
public class Root {

    private String fooString;
    private String barString;
    private JAXBElement<String> fooJAXBElement;
    private JAXBElement<String> barJAXBElement;

    private boolean setFoo;
    private boolean setBar;

    @XmlElement(nillable=true)
    public String getFooString() {
        return fooString;
    }

    public void setFooString(String foo) {
        this.fooString = foo;
        this.setFoo = true;
    }

    public boolean isSetFooString() {
        return setFoo;
    }

    @XmlElement(nillable=true)
    public String getBarString() {
        return barString;
    }

    public void setBarString(String bar) {
        this.barString = bar;
        this.setBar = true;
    }

    public boolean isSetBarString() {
        return setBar;
    }

    @XmlElementRef(name="fooJAXBElement")
    public JAXBElement<String> getFooJAXBElement() {
        return fooJAXBElement;
    }

    public void setFooJAXBElement(JAXBElement<String> fooJAXBElement) {
        this.fooJAXBElement = fooJAXBElement;
    }

    @XmlElementRef(name="barJAXBElement")
    public JAXBElement<String> getBarJAXBElement() {
        return barJAXBElement;
    }

    public void setBarJAXBElement(JAXBElement<String> barJAXBElement) {
        this.barJAXBElement = barJAXBElement;
    }

}

对象工厂

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name="fooJAXBElement")
    public JAXBElement<String> createFooJAXBElement(String string) {
        return new JAXBElement<String>(new QName("fooJAXBElement"), String.class, string);
    }

    @XmlElementDecl(name="barJAXBElement")
    public JAXBElement<String> createBarJAXBElement(String string) {
        return new JAXBElement<String>(new QName("barJAXBElement"), String.class, string);
    }

}

演示

下面是一个完整的例子来展示上面讨论的概念。

input.xml

此文档包含 2 个明确标记为 xsi:nil="true" 的元素和 2 个不存在的其他映射元素。

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <barString xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
    <barJAXBElement xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</root>

演示

此演示代码将读取上述 XML 并检查属性是否已作为解组的结果设置。

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class, ObjectFactory.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum20076018/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

        System.out.println("Was fooString set?  " + root.isSetFooString());
        System.out.println("Was barString set?  " + root.isSetBarString());
        System.out.println("Was fooJAXBElement set?  " + (root.getFooJAXBElement() != null));
        System.out.println("Was barJAXBElement set?  " + (root.getBarJAXBElement() != null));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

输出

下面是运行演示代码的输出。我们看到所有设置检查都是正确的,但输出仅与 JAXBElement 属性的输入完全匹配。

Was fooString set?  false
Was barString set?  true
Was fooJAXBElement set?  false
Was barJAXBElement set?  true
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <fooString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
    <barString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
    <barJAXBElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</root>

【讨论】:

  • 谢谢!当我将@XmlElement(nillable = true) 放在getter 上并检查是否已调用setter 将字段设置为null 时,它可以工作。只有一个小问题:如果我有一个type="xs:dateTime" 元素,那么我就有一个private Date dateFromXml 字段。如果 xml 中的日期未正确设置,例如 &lt;date&gt;blabla&lt;/date&gt;,则将调用 setter setDateFromXml(final Date dateFromXml) 将字段设置为 null - 与 xml 具有 xsi:nil="true" 时的行为相同。这个问题有解决办法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
相关资源
最近更新 更多