Search This Blog

Monday 24 June 2013

Inheritance in xsd

In the last post we were able to map elements which included attributes. An alternative way of representing elements is to nest them. Consider the below schema definition:
<element name="address">
  <complexType>
    <sequence>
      <element name="city" type="string" minOccurs="0"
        maxOccurs="1" default="-" />
      <element name="zipcode" type="string" nillable="false"
        minOccurs="1" maxOccurs="1" />
      <element name="country" type="string" fixed="India" />
    </sequence>
  </complexType>
</element>
The corresponding java class generated for the same is :
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "city", "zipcode", "country" })
@XmlRootElement(name = "address")
public class Address {

   @XmlElement(defaultValue = "-")
   protected String city;
   @XmlElement(required = true)
   protected String zipcode;
   @XmlElement(required = true)
   protected String country;
// setter getters
}
The XmlAttribute annotation that we saw in the previous post have been replaced by XmlElement annotation. On marshaling an instance of the class:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:address xmlns:ns2="http://test.com/xsd/simple/01/">
  <city>Pune</city>
  <zipcode>411020</zipcode>
</ns2:address>
Just as we saw in the previous post we can define a top level complex type and then have elements refer to the same.
<complexType name="cAddressType">
  <sequence>
    <element name="city" type="string" minOccurs="0" maxOccurs="1"
      default="-" />
    <element name="zipcode" type="string" nillable="false"
      minOccurs="1" maxOccurs="1" />
    <element name="country" type="string" fixed="India" />
  </sequence>
</complexType>
But why should we do this ?
One advantage (that we saw earlier too) is that we can create multiple elements created of the same type.
<element name="homeAddress" type="si:cAddressType" />
<element name="workAddress" type="si:cAddressType" />
The second is the ability to support inheritance. We can extend from complex types to create further complex types.
<complexType name="fullCAddressType">
  <complexContent>
    <extension base="si:cAddressType">
      <sequence>
        <!-- New elements are appended to the end -->
        <element name="address1" type="string" />
      </sequence>
    </extension>
  </complexContent>
</complexType>
The class created for the above is:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "fullCAddressType", propOrder = { "address1" })
public class FullCAddressType extends CAddressType {

   @XmlElement(required = true)
   protected String address1;
   //setter getters
}
On marshaling an instance of this type the xml is :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:homeFullAddress xmlns:ns2="http://test.com/xsd/simple/01/">
 <city>Pune</city>
 <zipcode>411020</zipcode>
 <address1>Local Street</address1>
</ns2:homeFullAddress>
The new property will always occur after the inherited properties.
Interestingly if we look in the code comments generated by xsd for any of the classes, we can see that the base value is specified for all the xsd types. For example consider the complete xsd definition for the fullCAddressType complexType :
<complexType name="fullCAddressType">
   <complexContent>
     <extension base="{http://test.com/xsd/simple/01/}cAddressType">
       <sequence>
         <element name="address1" type="{http://www.w3.org/2001/XMLSchema}string"/>
       </sequence>
     </extension>
   </complexContent>
 </complexType>
Here we have the base element that we specified. On the other hand for CAddressType:
<complexType name="cAddressType">
   <complexContent>
     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
       <sequence>
         <element name="city" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
         <element name="zipcode" type="{http://www.w3.org/2001/XMLSchema}string"/>
         <element name="country" type="{http://www.w3.org/2001/XMLSchema}string"/>
       </sequence>
     </restriction>
   </complexContent>
 </complexType>

1 comment: