JavaTM Architecture for XML Binding
JAXB RI Vendor Extensions
Experimental Schema Languages

Specification Version: 1.0
Reference Implementation (RI) Version: 1.0.5

Main: Release Notes | XJC | Ant task | Sample Apps | Changelog
JAXB RI Extensions: Runtime Properties | XJC Customizations
JAXB RI Schema Languages: W3C XML Schema | RELAX NG | DTD
JAXB Community: Java.net Homepage | Developer interest list | FAQ

The JAXB RI currently has experimental support for the schema languages listed on this page. The features listed on this page are not described by the JAXB Specification - they are only available in the JAXB RI.

Index

W3C XML Schema

This section outlines experimental support for W3C XML Schema features that are not required by the specification. This behavior is only available when the JAXB RI binding compiler is run with the "-extension" mode" enabled. Future versions of the JAXB Specification may describe portable bindings for these schema features.

Type Substitution Support  

Note: Type substitution support is experimental at present. JAXB 2.0 will specify the standard binding for type substitution. The JAXB RI currently only supports type substitution for complex types only. See Enabling Type Substitution for how to customize your schema to enable this support. Type substitution for an element declaration with a simple type definition will be supported in a subsequent release.

The following international purchase order example is taken from W3C XML Schema Part 0: Primer and which defines a couple of address types and a purchase order type:

 <complexType name="Address">
  <sequence>
   ...
  </sequence>
 </complexType>

 <complexType name="USAddress">
  <complexContent>
   <extension base="ipo:Address">
     ...
   </extension>
  </complexContent>
 </complexType>

 <complexType name="UKAddress">
  <complexContent>
   <extension base="ipo:Address">
     ...
   </extension>
  </complexContent>
 </complexType>
 
 <complexType name="PurchaseOrderType">
  <sequence>
   <element name="shipTo"     type="ipo:Address"/>
   <element name="billTo"     type="ipo:Address"/>
   ...
  </sequence>
  ...
 </complexType>

The following pseudo code represents what the JAXB RI generates for this schema:

interface Address { ... }
interface USAddress extends Address { ... }
interface UKAddress extends Address { ... }
interface PurchaseOrderType {
    Address getBillTo();
    void setBillTo(Address value);
    Address getShipTo();
    void setShipTo(Address value);
    ...
}
interface PurchaseOrder extends PurchaseOrderType, javax.xml.bind.Element {
    PurchaseOrderType getValueObject();
    void setValueObject(PurchaseOrderType value);
}

Type substitution enables an instance document to explicitly identify a derived type that supercedes an element declaration's schema specified type. Given local elements billTo and shipTo are mapped to JAXB properties with a base type of Address, type substitution allows instances of types that derive from Address to be set/get from the JAXB properties for billTo and shipTo. So for this case, it is possible to set instances of USAddress or UKAddress for JAXB properties billTo and shipTo. The xsi:type attribute (defined in the http://www.w3.org/2001/XMLSchema-instance namespace) specifies which address type is being used, as shown in the following XML fragment:

<ipo:purchaseOrder ... >

    <shipTo xsi:type="ipo:UKAddress">
        ...
    </shipTo>

    <billTo xsi:type="ipo:USAddress">
        ....
    </billTo>
    
    ...

</ipo:purchaseOrder>

In your client application code, you can simply rely on the type hierarchy derived from the schema and the type safety of the Java programming language to perform substitution. In the following code fragment (taken from samples/type-substitution/Main.java), you can see that instances of the different address types can be easily swapped:

    // unmarshal an instance doc that has a UKAddress in the <shipTo> element
    // and a USAddress in the <billTo> element
    PurchaseOrder po = 
        (PurchaseOrder)u.unmarshal( new FileInputStream( "ipo.xml" ) );

    // Process a return - Reverse purchase order addresses.
    Address billToAddress = po.getBillTo();
    Address shipToAddress = po.getShipTo();
    po.setBillTo(shipToAddress);
    po.setShipTo(billToAddress);

When marshalled back out, the new purchase order has the proper xsi:type attributes reversed:

<ipo:purchaseOrder ... >

    <shipTo xsi:type="ipo:USAddress">
        ...
    </shipTo>

    <billTo xsi:type="ipo:UKAddress">
        ....
    </billTo>
    
    ...

</ipo:purchaseOrder>
Generated getValueObject & setValueObject Methods

Running the binding compiler in -extension mode causes all complex schema derived types* that implement javax.xml.bind.Element to include two new API's setValueObject and getValueObject - as shown in the PurchaseOrder interface. These API's provide a way for you to access and perform type substitutions allowed by the schema.

*The JAXB RI currently supports type substitution for complex types only. As a result, element declarations with simple types like <xs:element name="comment" type="xs:string"/>, do not have get/setObjectValue() API's generated in their Java bindings. Type substitution for an element declaration with a simple type definition will be supported in a subsequent release.

The setValueObject API allows you to perform a type substitution within your client application. If we extend the sample above by creating a new USTaxExemptPurchaseOrderType:

     
<complexType name="USTaxExemptPurchaseOrderType">
  <complexContent>
    <extension base="ipo:PurchaseOrderType">
      <sequence>
        <element name="taxExemptId" type="xsd:string"/>
      </sequence>
    </extension>
  </complexContent>
</complexType>

Since USTaxExemptPurchaseOrderType derives by extension from PurchaseOrderType, instances of USTaxExemptPurchaseOrderType can be substituted for instances of PurchaseOrderType in your XML data. JAXB client applications can use the setValueObject API on PurchaseOrderType.java to perform a substitution with an instance of USTaxExemptPurchaseOrderType.java.

// unmarshal a PurchaseOrder
PurchaseOrder po = 
    (PurchaseOrder)u.unmarshal( new FileInputStream( "ipo.xml" ) );
    
// build a tax-exempt PO
USTaxExemptPurchaseOrderType uspo = 
    new ObjectFactory().createUSTaxExemptPurchaseOrderType();
// set fields on uspo
	    
// perform the type substitution
po.setValueObject(uspo);

Marshalling the po object causes the proper xsi:type attribute to appear in the XML data including the additional content added in the tax-exempt purchase order definition:

<purchaseOrder xsi:type="USTaxExemptPurchaseOrderType" ... >
    ...
    <taxExemptId>charity007</taxExemptId>
</purchaseOrder>

In order to access type substituted content of an element, the getValueObject API provides access to instances of the derived type (and the methods added to the derived type). For example, given the following XML fragment where a tax-exempt purchase order has been substituted for a regular purchase order:

<ipo:purchaseOrder xsi:type="ipo:USTaxExemptPurchaseOrderType" ...>
    ...
    <taxExemptId>charity44987</taxExemptId>
</ipo:purchaseOrder>

Your client application can unmarshal the content as a instance of the Java class PurchaseOrder, but you need to access it's value type and perform a cast before being able to access the data specific to the derived tax-exempt type:

po = (PurchaseOrder)u.unmarshal( new FileInputStream( "ustaxexemptpo.xml" ) );

// Access data added to element <ipo:purchaseOrder> via type substitution.
// All data added by derivation by extension from the element's original
// type specified in the schema must be accessed through this unwrapping
// of the element.
PurchaseOrderType pot = po.getValueObject();
if (pot instanceof USTaxExemptPurchaseOrderType) {
    USTaxExemptPurchaseOrderType taxexemptpo = (USTaxExemptPurchaseOrderType)pot;
    System.out.println("US Tax exempt id: " + taxexemptpo.getTaxExemptId());
}

See Implications of Type Substitution for Subclassing if using type substitution with application-specific implementation classes.

Substitution Group Support

In extension mode, the JAXB RI the JAXB RI generates code that handles element substitution group. For example, consider the following schema:

  <xs:complexType name="foo">
    <xs:sequence>
      <xs:element ref="head" />
    </xs:sequence>
  </xs:complexType>
  
  <xs:element name="head" type="t" />
  <xs:element name="sub"  type="t" substitutionGroup="head"/>
  
  <xs:complexType name="t">
    ...
  </xs:complexType>

The following pseudo-code represents what the JAXB RI generates for this schema:

interface Foo {
    Head head;
}
interface Head extends T {}
interface Sub extends T {}
interface T {
    ...
}

When a document containing a <sub> element is unmarshalled, the head property will return an instance of Sub. Similarly, if you set an instance of Sub interface and marshal it, you'll get a <sub> element.

For details of what type you should expect and what type you can set, see the API documentation of the generated interfaces.

Support for @block, @abstract, @final, @blockDefault, and @finalDefault attributes for the <complexType>, <element>, and <schema> elements

RELAX NG

See this document for details of RELAX NG support.

DTD

The JAXB RI is shipped with experimental DTD support, which lets you compile XML DTDs.

To compile a DTD test.dtd, run the XJC binding compiler as follows:

$ xjc.sh -dtd test.dtd

All the other command-line options of the XJC binding compiler can be applied, no matter what schema language you use. Similarly, the XJC ant task supports DTD. 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.

Customization

The customization syntax for DTD is roughly based on the ver.0.21 working draft of the JAXB specification, which is available at xml.coverpages.org. The deviations from this document are:


$Revision: 1.3 $
$Date: 2004/10/07 21:54:02 $