Marshalling with XSD choice field in class

萝らか妹 提交于 2019-12-24 07:36:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!