JAXB XJC code generation of element initializers with their declaration - jaxb

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.

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?

jaxb2 simplify plugin elements not simplified

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/>.

How to constrain set of attributes in xsd

All
Please suggest me how to restrict in xsd schema the following:
<root>
<node action="action1" parameter="1" />
</root>
I need to require attribute "parameter" only if attribute "action" is defined.
Thanks,
W3C Schema doesn't have the ability to express conditionally required attributes.
Schematron is a great tool for validating that documents adhere to custom validation scenarios in which content is conditionally required.
You could define those attributes as optional in your schema, and then use Schematron to validate it against those conditional rules.
I created this xsd to attempt to solve the problem.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="XMLSchema1"
targetNamespace="http://tempuri.org/XMLSchema1.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema1.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema1.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:group name="populated">
<xs:sequence >
<xs:element name="node">
<xs:complexType>
<xs:attributeGroup ref="actionattrib" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:group>
<xs:group name="unpopulated">
<xs:sequence >
<xs:element name="node">
<xs:complexType>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:group>
<xs:attributeGroup name ="actionattrib">
<xs:attribute name="action1" type="xs:string" />
<xs:attribute name="parameter" type="xs:int" />
</xs:attributeGroup>
<xs:element name="root">
<xs:complexType>
<xs:choice minOccurs ="0">
<xs:group ref="populated" />
<xs:group ref ="unpopulated" />
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
And a test method:
public static void Go()
{
string nameSpace = "http://tempuri.org/XMLSchema1.xsd";
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(nameSpace, "XMLSchema1.xsd");
XDocument myDoc1 = new XDocument(
new XElement(XName.Get("root", nameSpace),
new XElement( XName.Get("node", nameSpace ))
)
);
myDoc1.Validate(schemas, (o, e) => { Console.WriteLine(e.Message); });
}
And finally got this exception when validating:
Multiple definition of element 'http://tempuri.org/XMLSchema1.xsd:node' causes the content model to become ambiguous. A content model must be formed such that during validation of an element information item sequence, the particle contained directly, indirectly or implicitly therein with which to attempt to validate each item in the sequence in turn can be uniquely determined without examining the content or attributes of that item, and without any information about the items in the remainder of the sequence.
Which matches Mads result. His answer should be accepted.

JAXB generating wrong Namespace

I have a xsd (lets name it as afb) which imports another xsd (lets name it as kts). And I refer to an element of kts.xsd in afb.xsd along with correct namespaces.
But when I generate the classes using JAXB, the namespace for refered element is wrong.
I mean, the referred element should have kts namespace where as it is having afb namespace.
Because of which validating my XML against this xsd is failing also not able to bind the xml data into the java models.
EX:
afb.xsd :
<xs:import namespace="http://www.boschkts.com" schemaLocation="kts.xsd"/>
<xs:element name="vehicle">
<xs:complexType>
<xs:sequence>
<xs:element ref="vType"/>
<xs:element name="RESULTS" type="kts:RESULTS" >
</xs:sequence>
</xs:complexType>
</xs:element>
kts:xsd :
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.boschkts.com"
targetNamespace="http://www.boschkts.com" elementFormDefault="qualified">
<xs:complexType name="RESULTS">
<xs:sequence>
<xs:element name="SUMMARY" type="SUMMARY" minOccurs="0" />
</xs:sequence>
</xs:complexType>
Vehicle.java :
public class Vehicle {
#XmlElement(namespace = "http://www.boschafb.com", required = true)
protected String vType;
#XmlElement(name = "RESULTS", namespace = "http://www.boschafb.com", required = true)
protected Results results;
}
If I observe the Vehicle.java, the namespace of results property should have been "http://www.boschkts.com" instead of "http://www.boschafb.com"
If I change the namespace manually then binding the data from xml to java models works.
But still validating against the xsd fails with the error :
Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'kts:RESULTS'. One of '{"http://www.boschafb.com":RESULTS}' is expected.
Can anybody point what I might be missing in the xsd? or is it the way jaxb generates and I have to modify the classes manually?
Regards,
Satya
I'm assuing your abf.xsd starts with
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.boschafb.com"
targetNamespace="http://www.boschafb.com" elementFormDefault="qualified">
With elementFormDefault set to qualified, all element declarations, even nested ones, belong to the specified target namespace. Note that this applies only to elements, a referenced type does not affect the namespace of the element referencing it.
A solution would be to define an element instead of a type in 'kts.xsd' and referencing this element in your first schema:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.boschkts.com"
targetNamespace="http://www.boschkts.com" elementFormDefault="qualified">
<xs:element name="RESULTS">
<xs:complexType>
<xs:sequence>
<xs:element name="SUMMARY" type="SUMMARY" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.boschafb.com"
targetNamespace="http://www.boschafb.com" elementFormDefault="qualified"
xmlns:kts="http://www.boschkts.com">
<xs:import namespace="http://www.boschkts.com" schemaLocation="kts.xsd"/>
<xs:element name="vehicle">
<xs:complexType>
<xs:sequence>
<xs:element ref="vType"/>
<xs:element ref="kts:RESULT"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Try using an include instead of an import like so:
<xs:include schemaLocation="kts.xsd"/> instead of <xs:import namespace="http://www.boschkts.com" schemaLocation="kts.xsd"/>
This style causes far less problems with intra-namespace includes.

Resources