Java Architecture for XML Binding (JAXB) Reference Implementation (RI) is shipped with the RELAX NG support, which allows users to generate Java source code from a RELAX NG schema. This document explains how this extension of RI can be used.
This document assumes that you've already installed JAXB RI and you are comfortable with both compiling a schema and using the generated source code. Refer to the "JAXB User's Guide", which is a part of JAXB RI distribution, for general introduction of JAXB and JAXB RI.
JAXB RI RELAX NG Extension is not a stand-alone tool. You first need to download and install Java Web Services Developer Pack v1.1 (JWSDP).
Once you install JWSDP1.1, copy jaxb-1.0/lib/jaxb-xjc.jar
to jaxb-1.0/lib/jaxb-xjc.original.ja_
and then replace jaxb-1.0/lib/jaxb-xjc.jar
with the corresponding file in this distribution. It is strongly recommended to back up the original jaxb-xjc.jar file.
To compile a RELAX NG schema abc.rng
, run XJC as follows, just like you compile a XML Schema:
$ xjc.sh -relaxng abc.rng
This will compile abc.rng
and place the generated files into the current directory. All the other command-line options of XJC can be applied, no matter what schema language you use.
Similarly, the XJC ant task supports RELAX NG just like it supports XML Schema. For more information on the XJC ant task, refer to doc/ant.html
in the JAXB RI distribution.
No matter what schema language you use, the generated code will be no different. You'll use the same JAXB API to access the generated code.
JAXB customization declarations are tailored for W3C XML Schema, and as a result some of them doesn't fit well with RELAX NG. Also, we simply didn't have enough resource to support all the customization in this release. Hence although the customization syntax for RELAX NG is made similar to that for W3C XML Schema, there are some difference.
This section describes the supported customization in RELAX NG. All the examples are written by using inline annotation for tarseness, but the external customization is also supported. See the examples
directory for some examples.
Only package name is supported in <schemaBindings>. That is, the following is the only legal <schemaBindings> customization.
<schemaBindings> <package name="com.acme.foo" /> </schemaBindings>
However, in RELAX NG, this customization can be applied anywhere (in W3C XML Schema, this can be only applied to <xs:schema> element.) This customization takes effect only on the descendants of the node this customization is attached.
The following example shows how to put everything into one package.
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="1.0">
<jaxb:schemaBindings>
<jaxb:package name="com.acme.foo"/>
</jaxb:schemaBindings>
... all the other RELAX NG declarations ...
</grammar>
The following example shows how to divide the generated code into two packages by using <div> tag of RELAX NG:
<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="1.0"> <div> <jaxb:schemaBindings> <jaxb:package name="com.acme.foo"/> </jaxb:schemaBindings> ... RELAX NG declarations ... </div> <div> <jaxb:schemaBindings> <jaxb:package name="com.acme.bar"/> </jaxb:schemaBindings> ... RELAX NG declarations ... </div> </grammar>
If you have two schemas foo.rng
and bar.rng
and one includes the other, you can put them into two separate packages just by writing a <schemaBindings> element for each schema file.
Only the optional name attribute is supported. Therefore the following two are the only legal <class> customization in RELAX NG.
<class name="JavaClassName" /> <class />
However, in RELAX NG, this customization can be applied to any RELAX NG pattern or <define> (in W3C XML Schema, there's a limitation in where this customization can be applied.) Applying this customization to a RELAX NG pattern will map that pattern into a class. If the name attribute is unspecified, the compiler will derive one.
The following examples shows how a name of a class can be changed from its default to PersonRecord
by using a customization.
<element name="Person"
xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="1.0">
<jaxb:class name="PersonRecord"/>
<element name="first"><text/></element>
<element name="last"><text/></element>
</element>
This customization can be used to map something to a class when it's not mapped to a class by default. The following example illustrates how to map a part of a group to its own class.
<element name="Address"
xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="1.0">
<group>
<jaxb:class name="Name"/>
<element name="first"><text/></element>
<element name="last"><text/></element>
</group>
<element name="street"><text/></element>
<element name="city"><text/></element>
<element name="zip"><text/></element>
</element>
This customization can be also attached to a <define> block to map a pattern block to a class.
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="1.0">
<start>
<element name="root">
<ref name="sub"/>
</element>
</start>
<define name="sub">
<jaxb:class name="TSub"/>
... RELAX NG pattern ...
</define>
</grammar>
Only the optional name attribute is supported. Therefore the following two are the only legal <property> customization in RELAX NG.
<property name="PropertyName" /> <property />
However, in RELAX NG, this customization can be applied to any RELAX NG pattern or <define> (in W3C XML Schema, there's a limitation in where this customization can be applied.)
Applying this customization to a RELAX NG pattern will map that pattern into a property which objects from the descendants are assigned to. If the name attribute is unspecified, the compiler will derive one. Note that you probably wants to capitalize the first letter because otherwise you get method names like getproperty
instead of getProperty
.
The following simple example shows how a name of a property can be changed from its default by using a customization.
<element name="Person"
xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="1.0">
<element name="first"><text/></element>
<element name="last">
<jaxb:property name="FamilyName"/>
<text/>
</element>
</element>
This customization can be used to mimic the "general content list" behavior of JAXB W3C XML Schema binding. Consider the following example:
<element name="Person"
xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="1.0">
<group>
<jaxb:property name="Data"/>
<element name="first"><text/></element>
<element name="last"><text/></element>
</group>
</element>
Without a customization, two properties "First" and "Last" will be produced. But having a customization at the root of those two properties forces those two elements to be coerced into one list property "Data".
This is useful when you want to access the content model a a simple list when the content model is too complicated. The following example shows how to map a complicated content model into just one list property.
<element name="Root"
xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="1.0">
<group>
<jaxb:property name="Content"/>
<choice>
<element name="A"><text/></element>
<element name="B"><text/></element>
</choice>
<zeroOrMore>
<element name="C"><text/></element>
</zeroOrMore>
<element name="D"><text/></element>
</group>
</element>
This section describes other customizations designed specifically for RELAX NG.
RELAX NG by itself doesn't have a notion of inheritance. A <xjc:super> can be used to introduce the inheritance relationship between two generated interfaces. Technically this customization can be also applied to any RELAX NG pattern, but it is usually applied to a <ref /> pattern where a child interface is referencing its base interface.
The following example mimics the complex type derivation of BarType
from FooType
of W3C XML Schema:
<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="1.0"> <start> <element name="Root"> <ref name="BarType"/> </element> </start> <define name="BarType"> <ref name="FooType"> <xjc:super/> </ref> <attribute name="abc"/> <optional> <attribute name="def"/> </optional> </start> <define name="FooType"> <element name="fooContent"> <text/> </element> </define> </grammar>
In XML Schema, you can only append a new content model at the end of the base type. This restriction doesn't apply to RELAX NG. For exmample, you can prepend additional elements as follows:
<grammar xmlns="http://relaxng.org/ns/structure/1.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="1.0"> <start> <element name="Root"> <ref name="BarType"/> </element> </start> <define name="BarType"> <element name="header"><text/></element> <ref name="FooType"> <xjc:super/> </ref> <element name="footer"><text/></element> </start> <define name="FooType"> <element name="fooContent"> <text/> </element> </define> </grammar>
<xjc:interface> customization is another way to introduce a inheritance hierarchy in a way similar to the substitution group of W3C XML Schema. This customization can take the optional name attribute.
In many XML vocabularies, it is common to write a schema like this to represent a concept of "list" group:
Therefore it is nice if XJC can generate the ListBlock
interface and have OrderedList
,ItemizedList
, and SomeOtherTypeOfList
interfaces implement the ListBlock
interface.
This can be done ny specifying a <xjc:interface> customization as follows:
<define name="listBlock">
<xjc:interface />
<choice>
<ref name="orderedList"/>
<ref name="itemizedList"/>
<ref name="someOtherTypeOfList"/>
</choice>
</define>
This customization will generate an empty interface with the specified or derived name and have the subordinates implement this interface.
This customization can be also applied to <choice> itself:
<element name="package">
...
<element name="shipTo">
<choice>
<xjc:interface name="Address" />
<ref name="DomesticAddress"/>
<ref name="InternationalAddress"/>
</choice>
</element>
...
</element>
The effects of this customization are (1) the Address
interface is generated, (2) DomesitcAddress
and InternaltionalAddress
will implement this interface, and (3) the Package
class will have Address getShipTo()
and void setShipTo(Address)
methods.
There is no need for this customization and its child definitions to be separated by a <ref /> element. Definitions of DomesticAddress
and InternationalAddress
can be just inlined.
<element name="package">
...
<element name="shipTo">
<choice>
<xjc:interface name="Address" />
<element name="DomesticAddress">
... definition of domestic address ...
</element>
<element name="InternationalAddress">
... definition of international address ...
</element>
</choice>
</element>
...
</element>
Although Sun does not officially support the RELAX NG extension of JAXB RI, the JAXB team will provide technical support at users@jaxb.dev.java.net on best-effort basis. This is an archived mailing list, so you can post your comments or serach the archive from here, but you need to subscribe first by sending a blank e-mail to users-subscribe@jaxb.dev.java.net.