XJC: generate JAXB classes from invalid scheme - java

I want to generate a set of JAXB annotated classes of the OGC IndoorGML XML scheme (http://schemas.opengis.net/indoorgml/1.0/indoorgmlcore.xsd)
So I run xjc -d scr -p [packagename] -nv [path_to_xsd] (the -nv suppresses the strict validation of input schemes)
But running this command results in the following error messages:
[ERROR] Property "Rows" is already defined. Use <jaxb:property> to resolve this conflict.
line 653 of http://schemas.opengis.net/gml/3.2.1/geometryPrimitives.xsd
[ERROR] The following location is relevant to the above error
line 685 of http://schemas.opengis.net/gml/3.2.1/geometryPrimitives.xsd
[ERROR] Property "Title" is already defined. Use <jaxb:property> to resolve this conflict.
line 261 of http://www.w3.org/1999/xlink.xsd
[ERROR] The following location is relevant to the above error
line 246 of http://www.w3.org/1999/xlink.xsd
[ERROR] Property "Title" is already defined. Use <jaxb:property> to resolve this conflict.
line 232 of http://www.w3.org/1999/xlink.xsd
[ERROR] The following location is relevant to the above error
line 219 of http://www.w3.org/1999/xlink.xsd
and the class files are not being generated. This is strange, because I would expect these "official" schemes to be correct.
However, is there still any way to generate the java classes ignoring these errors?

After some trial and error and based on this xjb binding file, this command line will generate code
xjc -d src -XautoNameResolution -b indoor.xjb -nv indoorgmlcore.xsd
No package name is used, -XautoNameResolution is added and some extensions were removed. Comments inxjb file denote changes added to the original xjb. Latest version of xsd was used.
indoor.xjb contents:
<jaxb:bindings version="1.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc">
<!--
xmlns:wildcard="http://jaxb2-commons.dev.java.net/basic/wildcard"
xmlns:annox="http://annox.dev.java.net"
-->
<jaxb:bindings schemaLocation="http://schemas.opengis.net/gml/3.2.1/gml.xsd"
node="/xs:schema">
<jaxb:schemaBindings>
<jaxb:package name="net.opengis.gml.v_3_2"/>
</jaxb:schemaBindings>
</jaxb:bindings>
<jaxb:bindings schemaLocation="http://schemas.opengis.net/gml/3.2.1/geometryPrimitives.xsd" node="/xs:schema">
<jaxb:bindings>
<jaxb:bindings node="//xs:group[#name='PointGrid']/xs:sequence/xs:element[#name='rows']">
<!-- ** Backwards incompatible -->
<jaxb:property name="PointGridRows"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
<!-- StackOverflow 68692723 question -->
<jaxb:bindings schemaLocation="http://www.w3.org/1999/xlink.xsd" node="/xs:schema">
<jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='title']">
<jaxb:property name="XTitle"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
<jaxb:bindings schemaLocation="http://schemas.opengis.net/gml/3.2.1/coordinateOperations.xsd">
<jaxb:bindings node="//xs:element[#name='parameterValue']">
<jaxb:factoryMethod name="xparameterValue"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='operationParameter']">
<jaxb:factoryMethod name="xoperationParameter"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='OperationParameter']">
<jaxb:factoryMethod name="XOperationParameter"/>
</jaxb:bindings>
</jaxb:bindings>
<!-- StackOverflow 68692723 question END -->
<jaxb:bindings schemaLocation="http://schemas.opengis.net/gml/3.2.1/grids.xsd" node="/xs:schema">
<jaxb:bindings>
<jaxb:bindings node="xs:complexType[#name='GridType']/xs:complexContent/xs:extension/xs:sequence/xs:choice/xs:element[#name='axisLabels']">
<!-- ** Backwards incompatible -->
<jaxb:property name="GridAxisLabels"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
<jaxb:bindings schemaLocation="http://schemas.opengis.net/gml/3.2.1/datums.xsd" node="/xs:schema">
<jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='secondDefiningParameter']">
<jaxb:class name="SecondDefiningParameterPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='ellipsoid']">
<jaxb:factoryMethod name="EllipsoidPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='primeMeridian']">
<jaxb:factoryMethod name="PrimeMeridianPropertyElement"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
<jaxb:bindings schemaLocation="http://schemas.opengis.net/gml/3.2.1/coordinateReferenceSystems.xsd" node="/xs:schema">
<jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='userDefinedCS']">
<jaxb:factoryMethod name="UserDefinedCSPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='cartesianCS']">
<jaxb:factoryMethod name="CartesianCSPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='sphericalCS']">
<jaxb:factoryMethod name="SphericalCSPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='polarCS']">
<jaxb:factoryMethod name="PolarCSPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='linearCS']">
<jaxb:factoryMethod name="LinearCSPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='verticalCS']">
<jaxb:factoryMethod name="VerticalCSPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='cylindricalCS']">
<jaxb:factoryMethod name="CylindricalCSPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='ellipsoidalCS']">
<jaxb:factoryMethod name="EllipsoidalCSPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='affineCS']">
<jaxb:factoryMethod name="AffineCSPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='timeCS']">
<jaxb:factoryMethod name="TimeCSPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='imageDatum']">
<jaxb:factoryMethod name="ImageDatumPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='geodeticDatum']">
<jaxb:factoryMethod name="GeodeticDatumPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='temporalDatum']">
<jaxb:factoryMethod name="TemporalDatumPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='engineeringDatum']">
<jaxb:factoryMethod name="EngineeringDatumPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='verticalDatum']">
<jaxb:factoryMethod name="VerticalDatumPropertyElement"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:element[#name='conversion']">
<jaxb:factoryMethod name="ConversionPropertyElement"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Errors as below where fixed based on this page
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 243 of http://schemas.opengis.net/gml/3.2.1/coordinateOperations.xsd

Related

How to add interface on autogenerated jaxb elements by xsdtojava?

I want to add a super interface for a class autogenerated by jaxb and xsdtojava.
Problem: I can only add the interface on the root element (which I don't want, but just for testing purpose).
The element where I want to apply the inheritance is thelistelement.
The xsd I have not control of.
<xs:schema>
<xs:element name="myRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="thelist">
<xs:complexType>
<xs:sequence>
<xs:element name="thelistelement" maxOccurs="unbounded">
...
binding file:
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
jaxb:extensionBindingPrefixes="xjc inheritance"
jaxb:version="2.1">
<!-- this works -->
<jaxb:bindings schemaLocation="xsd/my.xsd">
<jaxb:bindings node="//xs:element[#name='myRequest']">
<inheritance:implements>MyInterface</inheritance:implements>
</jaxb:bindings>
</jaxb:bindings>
<!-- this does NOT work -->
<jaxb:bindings schemaLocation="xsd/my.xsd">
<jaxb:bindings node="//xs:element[#name='thelistelement']">
<inheritance:implements>MyInterface</inheritance:implements>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Running with <extensionArg>-Xinheritance</extensionArg>.
Output should be:
...
List<Thelistelement> thelist;
class Thelistelement implements MyInterface {
}
But the interface is missing on the list element class. Why then does it work on the root element myRequest?
I had to add an /xs:complexType to the node. Don't know why that worked though.
Important to note the single slash before the complexType!
<jaxb:bindings schemaLocation="xsd/my.xsd">
<jaxb:bindings node="//xs:element[#name='thelistelement']/xs:complexType">
<inheritance:implements>MyInterface</inheritance:implements>
</jaxb:bindings>
</jaxb:bindings>

Import JAXB binding snippet into other binding file

For a certain xsd file, I have created a corresponding binding file that does some actions. In my case, annotating ComplexTypes with annotations. Finding the type is done with an XPath expression. The following example demonstrates this:
<jaxb:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc"
version="2.1"
xmlns:annox="http://annox.dev.java.net" jaxb:extensionBindingPrefixes="annox">
<jaxb:bindings schemaLocation="FirstSchema.xsd" node="/xsd:schema">
<jaxb:bindings node="//xsd:complexType//xsd:element[contains(#type, 'SomeType')]" required="false">
<annox:annotate target="field">#com.example.Type(type = "SomeType")</annox:annotate>
</jaxb:bindings>
//About 100 lines of bindings
</jaxb:bindings>
</jaxb:bindings>
There are more bindings defined than just the single I've shown, but my problem is that the bindings are now executed on the FirstSchema.xsd. I have a lot of other xsd files that require the exact same bindings. If I have over 10 more xsd files, I'd have to copy-paste these bindings every time for every schema.
Is it possible to "extract" the bindings and re-use them for every other xsd file like an import? It's kind of related to this comment/question. The advised solution there is using jaxb:schemaBindings/jaxb:package, but if I understand correctly the following snippet just generates the classes into another package and doesn't really solve the problem?
<jaxb:schemaBindings>
<jaxb:package name="com.example.package"/>
</jaxb:schemaBindings>
You'll be surprized, but old-school XML inclusion works with XJB files.
binding.xjb:
<!DOCTYPE jaxb:bindings [
<!ENTITY gh24type SYSTEM "gh24type.xml">
]>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:annox="http://annox.dev.java.net"
jaxb:extensionBindingPrefixes="annox"
jaxb:version="2.1">
<jaxb:bindings schemaLocation="schema.xsd" node="/xsd:schema">
<!-- ... -->
&gh24type;
</jaxb:bindings>
</jaxb:bindings>
gh24type.xml:
<jaxb:bindings node="xsd:complexType[#name='gh24Type']">
<annox:annotate>#javax.annotation.Generated({"jaxb2-annotate-plugin"})</annox:annotate>
</jaxb:bindings>
So basically nothing spectacular, just entity-based XML inclusion. If you have exactly the same fragments, just include your entity several times for each of the schemas in question.
Alternatives would be writing a special plugin to simplify customization. Which might be a good idea anyway.

How to rename a xsd element during xjc java class generation?

I'm generating java classes from xsd with cxf-xjc-plugin.
<?xml version="1.0" encoding="utf-16"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="result">
...
</xsd>
I'm trying to rename the root element using a jaxb-binding.xml file:
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc"
jaxb:version="2.1">
<jaxb:bindings schemaLocation="xsd/myxsd.xsd" node="//xsd:element[#name='result']">
<jaxb:class name="MyNewName" />
</jaxb:bindings>
</jaxb:bindings>
But it does not work. The generated java class is named Result. What might be wrong here?

JAXB: Can't work around collision in ObjectFactory class error

I have a couple of SOAP services (implemented in .Net) that I want to generate a Java stub for. The first service was no problem but the second service threw up the error
WSDLToJava Error:
http://localhost/AMS52/ServiceManagement.svc?xsd=xsd8 [0,0]: Two declarations cause a collision in the ObjectFactory class.
http://localhost/AMS52/ServiceManagement.svc?xsd=xsd11 [0,0]: (Related to above error) This is the other declaration.
Not being too familiar with this stuff I eventually figured out that two imports in the wsdl are stepping on each other toes
<wsdl:types>
<xsd:schema targetNamespace="http://tempuri.org/Imports">
...
<xsd:import schemaLocation="http://localhost/AMS52/ServiceManagement.svc?xsd=xsd8" namespace="http://schemas.datacontract.org/2004/07/Company.Platform.Datatypes.Enums"/>
...
<xsd:import schemaLocation="http://localhost/AMS52/ServiceManagement.svc?xsd=xsd11" namespace="http://schemas.datacontract.org/2004/07/Company.Platform.Datatypes.ServiceManagement"/>
...
The xsd for the first import is of the form
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://schemas.datacontract.org/2004/07/Company.Platform.Datatypes.Enums"
elementFormDefault="qualified"
targetNamespace="http://schemas.datacontract.org/2004/07/Company.Platform.Datatypes.Enums">
<xs:simpleType name="DeviceIdiom">
<xs:restriction base="xs:string">
<xs:enumeration value="Auto"/>
<xs:enumeration value="Phone"/>
<xs:enumeration value="Tablet"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="DeviceIdiom" nillable="true" type="tns:DeviceIdiom"/>
<xs:simpleType name="ServiceManagementSORType">
...
More reading and I figured out I had to do something like this
How to resolve collision in the ObjectFactory on wsdl2java?
So my approach has been to try and put a suffix on the end of every simple type (they are all simple types).
So my current command line is
./wsdl2java.bat -impl -server -verbose -autoNameResolution -b bindings.xml ServiceManagement.wsdl
And my binding file is
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
jaxb:version="2.1">
<jaxb:bindings schemalocation="http://localhost/AMS52/ServiceManagement.svc?xsd=xsd8" node="/xs:schema">
<jaxb:bindings node="//xs:simpleType">
<jaxb:nameXmlTransform>
<jaxb:typeName suffix="Enums" />
</jaxb:nameXmlTransform>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
But now I am stuck on this error
XPath evaluation of "//xs:schema" results in empty target node
I can not figure out how to get past this error. I am starting to think it has something to do with the fact it's a .Net service and I have to reference the xsd like so
http://localhost/AMS52/ServiceManagement.svc?xsd=xsd8
Any help greatly appreciated.
Finally figured it out, I replaced
<jaxb:bindings schemalocation="http://localhost/AMS52/ServiceManagement.svc?xsd=xsd8" node="/xs:schema">
with
<jaxb:bindings schemaLocation="http://localhost/AMS52/ServiceManagement.svc?xsd=xsd8" node="/xs:schema">
Not easy to see is it, but note the capital L in schemaLocation - ouch!
Entire problem eventually fixed by mapping the schema for 'Company.Platform.Datatypes.Enums' to a different package with the binding file
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
jaxb:version="2.1">
<jaxb:bindings schemaLocation="http://localhost/AMS52/ServiceManagement.svc?xsd=xsd8">
<jaxb:schemaBindings>
<jaxb:package name="org.tempuri.enums"/>
</jaxb:schemaBindings>
</jaxb:bindings>

JAXB Root Class Rename using binding.xml

I use the Dali plugin in Eclipse to generate Java classes using an xsd file, which essentially just invokes xjc on the schema file. I used the advice here to resolve naming conflicts by applying an XML binding file to the class generation. This worked well, but I tried to take it a step further by renaming the root element, and the result was that I lost the XmlRootElement annotation. I tried using annox to add the root element annotation back in, but I get this error: Unsupported binding namespace "http://annox.dev.java.net". Perhaps you meant "http://java.sun.com/xml/ns/jaxb/xjc"?
Here is my initial binding.xml file (without annox):
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<!-- Force all classes to be generated at the top level, this will potentially cause name conflicts -->
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="mySchema-1.0.0.xsd">
<!-- Rename the root element -->
<jaxb:bindings node="//xs:element[#name='MyRootClassNameIsReallyLong']/xs:complexType">
<jaxb:class name="ShorterName"/>
</jaxb:bindings>
<!-- Rename the Bar class to resolve a naming conflict -->
<jaxb:bindings node="//xs:element[#name='Foo']/xs:complexType/xs:sequence/xs:element[#name='Bar']/xs:complexType">
<jaxb:class name="FooBar"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
By the way, it's worth noting that the schema file came from a third party, so I have no interest in modifying it. Likewise, I'd rather not tamper with the generated Java files, so that's why I am interested in the binding xml approach.
Edit (9/11/2013) - Here is the binding XML with annox:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
xmlns:annox="http://annox.dev.java.net"
version="2.1">
<!-- Force all classes to be generated at the top level, this will potentially cause name conflicts -->
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="mySchema-1.0.0.xsd">
<!-- Rename the root element -->
<jaxb:bindings node="//xs:element[#name='MyRootClassNameIsReallyLong']/xs:complexType">
<jaxb:class name="ShorterName"/>
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="MyRootClassNameIsReallyLong" />
</annox:annotate>
</jaxb:bindings>
<!-- Rename the Bar class to resolve a naming conflict -->
<jaxb:bindings node="//xs:element[#name='Foo']/xs:complexType/xs:sequence/xs:element[#name='Bar']/xs:complexType">
<jaxb:class name="FooBar"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Annox is an XJC add on, so you in addition to declaring the namespace prefx (xmlns:annox="http://annox.dev.java.net), you also need to declare it as an extensionBindingPrefix.
Your openning tag should then look like this:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb
http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
jaxb:extensionBindingPrefix="annox"
version="2.1">

Categories

Resources