I am working on an internal project in my spare time at IBM that requires some marshalling of XML using Java. The obvious candidate is JAXB which in the main works very well. However when it fails, information on the web can be frustrating, telling you to fix it using <jaxb:property>
but not actually giving you any useful information. I admit this is for a specific error that I needed to fix, but I do not think it is uncommon.
Therefore I have written a short xsd example that when run through xjc.sh
(or xjc.bat
on windows) exhibits the same error I was getting. The contents of the Dummy.xml
file are as follows (sorry for formatting, wordpress not me!):
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="complexTypeOne">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="value" type="simpleTypeOne"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="complexTypeTwo">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="value" type="simpleTypeTwo"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:simpleType name="simpleTypeTwo">
<xsd:restriction base="xsd:string">
<xsd:pattern value="[0123456789]+"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="simpleTypeOne">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="exist"/>
<xsd:enumeration value="noexist"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
The Dummy.xml
file consists of two complexTypes with an attribute of the same name, not a huge problem as the Java XML parsers run quite happily when validating XML, but when it comes to using JAXB code generation it falls over. In this case the same name is value and when run with xjc.sh
produces the following error:
Property "Value" is already defined. Use <jaxb:property> to resolve this conflict.
The way to fix this issue is indeed to use a <jaxb:property>
tag, and the way I found to fix this was using an external bindings file. This file will detail alternate names to use for the clashing names and will allow JAXB to parse without throwing errors. The bindings.xsd
can be found here:
<jxb:bindings version="2.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="Dummy.xml" node="/xsd:schema">
<jxb:bindings node="//xsd:complexType[@name='complexTypeOne']">
<jxb:bindings node=".//xsd:attribute[@name='value']">
<jxb:property name="ValueToFixError1"/>
</jxb:bindings>
</jxb:bindings>
<jxb:bindings node="//xsd:complexType[@name='complexTypeTwo']">
<jxb:bindings node=".//xsd:attribute[@name='value']">
<jxb:property name="ValueToFixError2"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
The bindings.xsd
defines the xml file to perform the modifications to (schemaLocation="Dummy.xml"
) and then specifies using XPATH notation the relevant values to change. Fairly self explanatory if you can see the files for yourself, less so if you are just told to use tags! To specify the
bindings.xsd
on the command line simply do: xjc.sh -b bindings.xsd Dummy.xml
which should now compile your code