我们使用 Jaxb (jaxb-api 2.2.5) 从 XSD 生成 Java 类。 'someField' 元素具有 nillable='true' 属性和(隐式)minoccurrs='1'。还有一个可选的“order”属性。
当我们在 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 生成后者吗? JAXB 在生成无 nil 版本时实际上是错误的吗?
最佳答案
And is JAXB actually wrong in generating the nil-less version?
让我回复您。
Do you know how we can get JAXB be to generate the latter?
以下是您可以执行的操作
Java 模型
某些父类型
要通过现有 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>
关于soap - JAXB 'forgets' 在设置属性值但未设置元素值时添加 nil ='true',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26657098/