jaxb2 simplify plugin elements not simplified - xsd

I have tried to convert XSD to JAXB classes using mave-jaxb2 plugin and jaxb2-basics simplify plugin.
The configuration in pom.xml is available in this post
sample.xsd (complex choice type)
<xs:complexType name="doclist">
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="document1" type="type1">
<xs:annotation>
<xs:appinfo>
<simplify:as-reference-property/>
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="document2" type="type2">
</xs:element>
</xs:choice>
</xs:sequence>
<xs:attribute name="heading" type="xs:string" />
</xs:complexType>
However the generated JAXB classes have aOrB references.
#XmlElements({
#XmlElement(name = "document1", type = Type1.class),
#XmlElement(name = "document2", type = Type2.class)
})
protected List<Object> document1OrDocument2;

You have an elements property so you have to place your annotation on the xs:choice, not on the xs:element. Please see the documentation.
And you most probably want to use <simplify:as-element-property/>.

Related

specifying a JAXB external binding for XSD sequence nodeName and choice/sequence nodeName

I'm trying to eliminate "Element "___" shows up in more than one properties" with jxb external bindings on a xsd I don't maintain.
I can modify the XSD with the following that works:
<xs:complexType name="credit">
<xs:sequence>
<xs:element .../>
<xs:element name="link" type="link" minOccurs="0" maxOccurs="unbounded">
<xs:annotation> <xs:appinfo> <jxb:property name="linkElement"/> </xs:appinfo> </xs:annotation>
</xs:element>
<xs:choice>
<xs:sequence>
...
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="link" type="link" minOccurs="0" maxOccurs="unbounded"/>
...
</xs:sequence>
</xs:sequence>
</xs:choice>
</xs:sequence>
...
to create the sequence linkElement of type Link and sequence of choices:
#XmlElement(name = "link")
protected List<Link> linkElement;
...
#XmlElements({
#XmlElement(name = "link", type = Link.class),
...
})
protected List<Object> linkAndBookmarkAndCreditWords;
but when I try a JAXB external binding file with the likes of:
<jxb:bindings node="//xs:complexType[#name='credit']//xs:sequence//xs:element[#name='link']" >
<jxb:property name="linkElement" />
</jxb:bindings>
I get the error:
[ERROR] XPath evaluation of "...[#name='link']" results in too many (2) target nodes
How can I distinguish only the first "link" node as I do in the internal bindings?
You XPath-expression is not precise enough. These // mean "anywhere below current node". This includes both of your link elements.
Try making your XPath-expression more precise, something along the lines:
xs:complexType[#name='credit']/xs:sequence/xs:element[#name='link']

JAXB: xjc and fixed values for attributes of derived types

I'm trying to create an xsd with a type hierarchy.
What I'm hoping to archieve is that the subtypes fill the base type's attributes with a certain value.
This is my best result:
<xs:complexType name="base_type">
<xs:attribute name="att" use="required" type="xs:string" />
</xs:complexType>
<xs:complexType name="type1_t">
<xs:complexContent>
<xs:restriction base="base_type">
<xs:attribute name="att" fixed="value1" use="required" type="xs:string" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="type2_t">
<xs:complexContent>
<xs:restriction base="base_type">
<xs:attribute name="att" fixed="value2" use="required" type="xs:string" />
</xs:restriction>
</xs:complexContent>
</xs:complexType>
The "att" attribute is made available by base_type, and in elements of type1_t and type2_t, I'd like them set to "value1" and "value2", respectively.
The container element looks like this:
<xs:element name="root">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="type1" type="type1_t" />
<xs:element name="type2" type="type2_t" />
</xs:choice>
</xs:complexType>
</xs:element>
Now I'm running xjc to generate Java classes for this code, but the "fixed" attribute is not represented in what I get in the Type1T.java, which consists only of
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "type1_t")
public class Type1T extends BaseType { }
I would have expected
{
#Override public String getAtt() { return "value1"; }
}
?
That is (almost) what gets generated when the type is generated by itself (ie not as an extension of a base type).
I'm I doing something wrong? Is what I'm trying to do just not possible?
My goal is to automatically generate all java code from xsd; otherwise I suppose a way to implement this would be to code the fixed values in the created ObjectFactory methods for each class manually. However, then I would need to prevent ObjectFactory from getting generated every time...
Any hints? Tips? Thoughts?

XSD and JAXB for sequence of repeating elements

I am creating a XSD to represent the following XML structure.
<DETAILS>
<REFERENCE></REFERENCE>
<INFORMATION>
<INFO>
<KEY></KEY>
<VALUE></VALUE>
<KEY></KEY>
<VALUE></VALUE>
<KEY></KEY>
<VALUE></VALUE>
<KEY></KEY>
<VALUE></VALUE>
.....
</INFO>
</INFORMATION>
I intend to use the same XSD to generate JAXB annotated java classes using XJC.
I manage to get the following XSD.
<xs:complexType name="DetailsType">
<xs:annotation>
<xs:appinfo>
<jaxb:class name="Details" />
</xs:appinfo>
</xs:annotation>
<xs:sequence>
<xs:element type="xs:int" name="REFERENCE">
<xs:annotation>
<xs:appinfo>
<jaxb:property name="reference" />
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element type="InformationType" name="INFORMATION">
<xs:annotation>
<xs:appinfo>
<jaxb:property name="Information" />
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="InformationType">
<xs:annotation>
<xs:appinfo>
<jaxb:class name="Information" />
</xs:appinfo>
</xs:annotation>
<xs:sequence>
<xs:element name="INFO" type="InfoType">
<xs:annotation>
<xs:appinfo>
<jaxb:property name="Info" />
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="InfoType">
<xs:annotation>
<xs:appinfo>
<jaxb:class name="Info" />
</xs:appinfo>
</xs:annotation>
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="KEY" type="xs:string" />
<xs:element name="VALUE" type="xs:string" />
</xs:sequence>
</xs:complexType>
However using this XSD, XJC generates Java classes using JAXBElement, something like,
#XmlElementRefs({
#XmlElementRef(name = "KEY", type = JAXBElement.class),
#XmlElementRef(name = "VALUE", type = JAXBElement.class)
})
protected List<JAXBElement<String>> keysAndValues;
For such a trivial XML of sequence of repeating elements, the overhead of using JAXBElement seems quite annoying.
Am I missing something ?
I am open to a different approach for XSD Or can someone provide a way to tell JAXB to generate more meaningful classes (don't use JAXBElement please) ?

Java Code for creating child elements within an element

I want to generate the following XSD Schema using JAXB and ObjectFactory class of org/w3/_2001/xmlschema
<xs:element name="result">
<xs:complexType>
<xs:sequence>
<xs:element name="sfobject" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="id"/>
<xs:element type="xs:string" name="type"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
But I am getting XSD as :
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="result">
<xs:complexType>
<xs:sequence/>
</xs:complexType>
</xs:element>
<xs:element name="sfobject" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence/>
</xs:complexType>
</xs:element>
<xs:element type="xs:string" name="id"/>
<xs:element type="xs:string" name="type"/>
</xs:schema>
I am not able to add one element inside other element. How do I do that in Java using JAXB and ObjectFactory methods.
Sample Code:
List schemaElementList = schema.getSimpleTypeOrComplexTypeOrGroup();
TopLevelElement resultElement = xsdObjFactory.createTopLevelElement();
resultElement.setName("result");
LocalComplexType resultCompType = xsdObjFactory.createLocalComplexType();
resultElement.setComplexType(resultCompType);
resultCompType.setSequence(expGroup);
Element sfElement = (Element)xsdObjFactory.createLocalElement();
sfElement.setName("sfobject");
sfElement.setMaxOccurs("unbounded");
sfElement.setMinOccurs(new BigInteger("0"));
LocalComplexType sfCompType = xsdObjFactory.createLocalComplexType();
sfElement.setComplexType(sfCompType);
schemaElementList.add(resultElement);

JAXB XJC code generation of element initializers with their declaration

If I have a schema such as the following:
<xs:element name="Book">
<xs:complexType>
<xs:sequence>
<xs:element ref="Chapter" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Chapter">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="Word" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Word">
</xs:element>
It will generate something like:
#XmlRootElement(name = "Book")
public class Book {
#XmlElement(name = "Chapter", required = true)
protected Chapter chapter;
Is it possible to generate the following instead?
#XmlElement(name = "Chapter", required = true)
protected Chapter chapter = new Chapter();
This is so that even if an XML file is missing a Chapter element within a Book, when it is unmarshalled there will still be a Book object created so it is possible to do
book.getChapter().getWord() and retrieve an empty list, instead of checking for null.
You can create a plugin. I've written a short tutorial that helps you do exactly that. Hope you find it helpful.

Resources