问题
I use a Java class to generate the WSDL schema dynamically. I have this as one of my fields:
@XmlElements({
@XmlElement(name = "A", type = String.class),
@XmlElement(name = "B", type = Integer.class),
@XmlElement(name = "C", type = String.class),
@XmlElement(name = "D", type = String.class)
})
protected Object aOrBOrCOrD;
During marshalling, when the single choice property aOrBOrCOrD is set, which tag name(A, B, C or D) would be set in the XML?
Since there's only one field which would contain the data. And String could also mean any 1 of the 3 choice elements. How to get around this?
Can I split the single field in 4 and still maintain the choice property when the WSDL is generated somehow?
回答1:
You could do the following:
Java Model
Foo
Instead of @XmlElements
and a property of type Object
, you can use @XmlElementRefs
and a property of type JAXBElement
. A JAXBElement
allows you to preserve the element name.
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {
@XmlElementRefs({
@XmlElementRef(name = "A", type = JAXBElement.class),
@XmlElementRef(name = "B", type = JAXBElement.class),
@XmlElementRef(name = "C", type = JAXBElement.class),
@XmlElementRef(name = "D", type = JAXBElement.class)
})
protected JAXBElement<?> aOrBOrCOrD;
}
ObjectFactory
Along with @XmlElementRef
you need to have a corresponding @XmlElementDec
annotations on a class annotated with @XmlRegistry
.
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
@XmlElementDecl(name="A")
public JAXBElement<String> createA(String value) {
return new JAXBElement<String>(new QName("A"), String.class, value);
}
@XmlElementDecl(name="B")
public JAXBElement<Integer> createB(Integer value) {
return new JAXBElement<Integer>(new QName("B"), Integer.class, value);
}
@XmlElementDecl(name="C")
public JAXBElement<String> createC(String value) {
return new JAXBElement<String>(new QName("C"), String.class, value);
}
@XmlElementDecl(name="D")
public JAXBElement<String> createD(String value) {
return new JAXBElement<String>(new QName("D"), String.class, value);
}
}
Demo Code
Demo
import java.io.StringReader;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Foo.class, ObjectFactory.class);
StringReader xml = new StringReader("<foo><C>Hello World</C></foo>");
Unmarshaller unmarshaller = jc.createUnmarshaller();
Foo foo = (Foo) unmarshaller.unmarshal(xml);
JAXBElement<?> aOrBOrCOrD = foo.aOrBOrCOrD;
System.out.println(aOrBOrCOrD.getName().getLocalPart());
System.out.println(aOrBOrCOrD.getDeclaredType());
System.out.println(aOrBOrCOrD.getValue());
}
}
Output
C
class java.lang.String
Hello World
来源:https://stackoverflow.com/questions/23779674/marshalling-with-xsd-choice-field-in-class