I have several XSDs that reuse the same entities. For example, both the XSDs for the ProductPurchaseRequest.xsd
and ProductQuoteRequest.xsd
both have a <product>
tag in them to describe the product in question. For this reason I created a Product.xsd
file to define the <product>
tag and both ProductPurchaseRequest.xsd
and ProductQuoteRequest.xsd
import the Product.xsd
with a `.
I would like to use Castor to generate Java classes from theses XSDs, and for both of them to use the same class for representing the Product
so that I could reuse the same logic for mapping them to our model's ProductModel
class.
Can Castor do this? If so, what would be the Ant task syntax for it. If not, would perhaps JAXB be a better alternative?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
Can Castor do this? If so, what would be the Ant task syntax for it. If not, would perhaps JAXB be a better alternative?
Below is an example of how this could be done using JAXB:
Product
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/Product"
xmlns:tns="http://www.example.org/Product"
elementFormDefault="qualified">
<element name="product">
<complexType>
<sequence>
<element name="id" type="string"/>
<element name="name" type="string"/>
</sequence>
</complexType>
</element>
</schema>
Since multiple XML schemas import Product.xsd we can leverage episode files so that the classes corresponding to Product.xsd are only generated once.
xjc -d out -episode product.episode Product.xsd
ProductPurchaseRequest.xsd
Below is an example of an XML schema that imports Product.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/ProductPurchaseRequest"
xmlns:tns="http://www.example.org/ProductPurchaseRequest"
xmlns:prod="http://www.example.org/Product"
elementFormDefault="qualified">
<import namespace="http://www.example.org/Product" schemaLocation="Product.xsd"/>
<element name="purchase-request">
<complexType>
<sequence>
<element ref="prod:product" maxOccurs="unbounded"/>
</sequence>
</complexType>
</element>
</schema>
When we generate classes from this XML schema we will reference the episode file we created when we generated Java classes from Product.xsd.
xjc -d out ProductPurchaseRequest.xsd -extension -b product.episode
ProductQuoteRequest.xsd
Below is another example of an XML schema that imports Product.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/ProductQuoteRequest"
xmlns:tns="http://www.example.org/ProductQuoteRequest"
xmlns:prod="http://www.example.org/Product"
elementFormDefault="qualified">
<import namespace="http://www.example.org/Product" schemaLocation="Product.xsd"/>
<element name="quote">
<complexType>
<sequence>
<element ref="prod:product"/>
</sequence>
</complexType>
</element>
</schema>
Again when we generate classes from this XML schema we will reference the episode file we created when we generated Java classes from Product.xsd.
xjc -d out ProductQuoteRequest.xsd -extension -b product.episode
For More Information
So I was able to get the whole thing working using the JAXB reference implementation. The trick was to realise that the download from JAXB site is a downloader and not the actual libraries! Double-click to accept the licence and the libraries will download locally. Created a test folder (JAXB_TEST
) and copied all the downloaded .jar
s to a lib
subfolder. I put all my XSDs in XSD
subfolder. After that I ran the following Ant build.xml
file.
<?xml version="1.0"?>
<project name="jaxb_test" basedir="." default="package" >
<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
<classpath>
<fileset dir="./lib" includes="*.jar" />
</classpath>
</taskdef>
<target name="generate">
<delete dir="./gen-src" />
<mkdir dir="./gen-src" />
<xjc destdir="./gen-src" language="XMLSCHEMA" package="com.mmm" >
<schema dir="./xsd" includes="EPC*.xsd" />
</xjc>
</target>
<target name="compile" depends="generate" >
<delete dir="./bin" />
<mkdir dir="./bin" />
<javac srcdir="./gen-src" destdir="./bin" includeantruntime="false" />
</target>
<target name="package" depends="compile" >
<delete dir="./dist" />
<mkdir dir="./dist" />
<jar destfile="./dist/jaxb-gen.jar" basedir="./bin" />
</target>
</project>
The only problem I had was that I had an xsd with a root tag called <product>
that anonymous extended the Product
type to add a version
attribute (which I always like to have on my root tag's) which was causing a name conflict for JAXB. So instead, I turned the anonymous type into a named type (i.e. TopLevelProduct
) and set the root to that type and JAXB was happy with that.
来源:https://stackoverflow.com/questions/7986082/can-castor-handle-class-generation-from-multiple-xsds-importing-from-a-base-xsd