How do I separate the <xsd:choice/> sub-elements into individual Collection properties using JAXB?
I have the following XSD
fragment that is from a Vendor, I can't change the way it is specified:
<xsd:element name="navmap">
<xsd:complexType>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="navitem"/>
<xsd:element ref="debug"/>
</xsd:choice>
<xsd:attribute name="focus" type="xsd:string" use="optional"/>
</xsd:complexType>
</xsd:element>
Right now wi开发者_高级运维th no customizations it generates the following code
@XmlElements({
@XmlElement(name = "navitem", type = Navitem.class),
@XmlElement(name = "debug", type = Debug.class)
})
protected List<Object> navitemOrDebug;
I would rather it generate a separate list for each type like below
@XmlElements({
@XmlElement(name = "navitem", type = Navitem.class)
})
protected List<Navitem> navitems;
@XmlElements({
@XmlElement(name = "debug", type = Debug.class)
})
protected List<Debug> debugs;
I have the following in my .xjb
file that renames the entire List
but I can't figure out how to split them up.
<jxb:bindings node="//xsd:element[@name='navmap']//xsd:complexType//xsd:choice">
<jxb:property name="contents" />
</jxb:bindings>
How do I specify that I want a separate List
or Set
for each of the types in an external .xjb
binding file?
If I can't do that, How do I add an <jaxb:annotation/>
to the .xsd
file to specify a separate List
or Set
for each of the types?
I don't care about ordering, the order is not important in this particular case.
NOTE: I would prefer an external .xjb
solution, I don't want to have to diff a custom .xsd against every new version the vendor provides, there are too many of them.
As promised, please meet the Simplify Plugin.
This plugin allows simplifying "complex" properties. Thes properties are often generated from repeatable choices like this one:
<xs:complexType name="typeWithReferencesProperty">
<xs:choice maxOccurs="unbounded">
<xs:element name="a" type="someType"/>
<xs:element name="b" type="someType"/>
</xs:choice>
</xs:complexType>
...
<xs:complexType name="typeWithElementsProperty">
<xs:choice maxOccurs="unbounded">
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:int"/>
</xs:choice>
</xs:complexType>
By default, XJC will complex properties modelling several references or elements in one.
@XmlElementRefs({
@XmlElementRef(name = "a", type = JAXBElement.class),
@XmlElementRef(name = "b", type = JAXBElement.class)
})
protected List<JAXBElement<SomeType>> aOrB;
...
@XmlElements({
@XmlElement(name = "a", type = String.class)
@XmlElement(name = "b", type = Integer.class),
})
protected List<Serializable> aOrB;
These complex properties are required to model complex content of the XML schema adequately, i.e. to maintain the order of the elements in the repeatable choice. Unfortunately, they are not idiomatic as bean properties. These properties are "heterogeneous" (in a sense that they store different types), which makes it hard to work with them.
However, if the order of the elements is not significant - that is, you can live with the fact that it will change afte re-marshalling, the structures of these properties can be simplified: complex properties can be split into several simple properties.
The Simplify Plugin implements this task. It allows you to simplify your complex properties. The plugin will remove the complex property and insert several simpler properties instead of the original (complex) property. So you can get something like:
@XmlElement(name = "a", type = String.class)
protected List<String> a;
@XmlElement(name = "b", type = Integer.class)
protected List<Integer> b;
Or:
@XmlElement(name = "a")
protected List<SomeType> a;
@XmlElement(name = "b")
protected List<SomeType> b;
Or:
@XmlElementRef(name = "a", type = JAXBElement.class)
protected List<JAXBElement<SomeType>> a;
@XmlElementRef(name = "b", type = JAXBElement.class)
protected List<JAXBElement<SomeType>> b;
Dependin on the customization.
The plugin will be released in JAXB2 Basics 0.6.3, now availavle as a snapshot from this repository.
As far as I know, at the moment you can't (with XJC from JAXB RI). Theoretically it must possible to write a plugin which changes the XJC model.
But you must be aware that two separate homogeneous properties debug
and navitem
do not equal one heterogeneous property navitemOrDebug
. I.e. you'll get a different ordering of the elements if you unmarshall and marshall the same object.
However, in many cases this might make sense. Please file an issue here, I'll consider implementing it.
精彩评论