【问题标题】:JAXB 'forgets' to add nil='true' when attribute value is set, but element value is notJAXB'忘记'在设置属性值时添加 nil='true',但元素值不是
【发布时间】:2014-12-26 17:40:08
【问题描述】:

我们使用 Jaxb (jaxb-api 2.2.5) 从 XSD 生成 Java 类。 'someField' 元素具有 nillable='true' 属性和(隐式)minoccurs='1'。还有一个可选的“订单”属性。

当我们在 someField 上设置 order 属性但没有值时,JAXB 将在没有 nill='true' 的请求中生成 XML 元素,这不会被 XSD 接受并导致 SOAP 错误。

字段的 XSD:

<xs:element name="someField" nillable="true">
    <xs:complexType>
        <xs:simpleContent>
            <xs:extension base="iata:AlphaNumericStringLength1to19">
                <xs:attribute name="order" type="xs:integer" use="optional"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>
</xs:element>

Jaxb 将其转换为我们 Java 类中的以下字段:

@XmlElement(required = true, nillable = true)
protected SomeParentType.SomeField someField;

SomeField 类如下所示:

public static class SomeField{

    @XmlValue
    protected String value;
    @XmlAttribute
    protected BigInteger order;

    // getters  + setters
}

当我们将 order ATTRIBUTE 设置为 2(例如),并且没有设置任何值时,JAXB 将生成:

<pay1:someField order="2"/> 

根据 XSD,这是无效的,当我们发送它时会导致 SOAP 错误。

这确实有效:

<pay1:someField xsi:nil="true" order="2"/>

你知道我们如何让 JAXB be 生成后者吗? JAXB 在生成 nil-less 版本时实际上是错误的吗?

【问题讨论】:

    标签: soap attributes jaxb null


    【解决方案1】:

    JAXB 在生成 nil-less 版本时实际上是错误的吗?

    让我回复你。


    你知道我们如何让 JAXB be 生成后者吗?

    以下是你可以做的事情

    Java 模型

    SomeParentType

    要使用现有 JAXB 库获得您正在寻找的行为,域模型需要采用以下形式:

    import java.math.BigInteger;
    import javax.xml.bind.JAXBElement;
    import javax.xml.bind.annotation.*;
    
    @XmlRootElement
    public class SomeParentType {
    
        @XmlElementRef(name="someField")
        protected JAXBElement<SomeParentType.SomeField> someField;
    
        public static class SomeField{
    
            @XmlValue
            protected String value;
            @XmlAttribute
            protected BigInteger order;
    
            // getters  + setters
        }
    
    }
    

    注册表

    要与@XmlElementRef 一起使用,我们需要在带有@XmlRegistry 注释的类上有一个@XmlElementDecl

    import javax.xml.namespace.QName;
    import javax.xml.bind.*;
    import javax.xml.bind.annotation.*;
    
    @XmlRegistry
    public class Registry {
    
        @XmlElementDecl(name="someField")
        public JAXBElement<SomeParentType.SomeField> createSomeField(SomeParentType.SomeField someField) {
            return new JAXBElement(new QName("someField"), SomeParentType.SomeField.class, someField);
        }
    
    }
    

    演示代码

    下面是一些演示代码来练习您的用例:

    import javax.xml.bind.*;
    import java.math.BigInteger;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            // Create the JAXBContext to bring in the Registry
            JAXBContext jc = JAXBContext.newInstance(SomeParentType.class, Registry.class);
    
            // Create the instance of SomeField
            SomeParentType.SomeField sf = new SomeParentType.SomeField();
            sf.order = new BigInteger("1");
    
            // Wrap the SomeField in a JAXBElement & specify the nil aspect
            Registry registry = new Registry();
            JAXBElement<SomeParentType.SomeField> jaxbElement = registry.createSomeField(sf);
            jaxbElement.setNil(true);
    
            SomeParentType spt = new SomeParentType();
            spt.someField = jaxbElement;
    
            // Marshal the domain model to XML
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(spt, System.out);
        }
    
    }
    

    输出

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <someParentType>
        <someField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" order="1" xsi:nil="true"/>
    </someParentType>
    

    【讨论】:

    • 感谢您的详尽解释。我们会试试这个,看看它是否适合我们。
    • 嗨,布莱斯,还有一个问题。我们想知道您建议的解决方案是否是此问题的唯一解决方案。是否有可能让 JAXB 在不使用自定义代码的情况下创建 nill=true 属性?而且我对您对 JAXB '忘记' nill=true 属性的看法也很感兴趣。您的帖子表明这是 JAXB 中的一个有意识的实现选择。我很好奇为什么,因为我的感觉是 nill 与值有关,当值不存在时,这意味着 nill=true 应该在 XML 中,即使有一个 order 属性。提前致谢。 J
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多