Complex Content

The XSD ComplexContentelement < xsd:complexContent> is used to create a modified version of a base type through extension or restriction mechanisms. It is similar in concept to creating derived types in Java or C++.

Type Substitution and the Type Hierarchy

The use of complexContent with extensionor restrictioncreates a type hierarchy. XML Schema allows for type substitutions, by using the XML schema instance type attribute (xsi:type).

There are two ways XBinder will represent the XSD type hierarchy in the target language. One approach uses class extension. The second approach uses interfaces. With the extension approach, every subtype of BaseTypewill be modeled as a subclass of class BaseType. This means that any occurrences of type BaseTypecan be represented using a reference of class BaseType. This is what you would likely have expected.

With the interface approach, every subtype of BaseType, call it BaseSubType, will be modeled using class BaseSubType, but BaseSubTypemay or may not be a subclass of BaseType. Instead, BaseSubTypewill implement (directly or indirectly) an interface named BaseType_derivations. Any occurrences of type BaseTypewill be represented using a reference of interface BaseType_derivations.

The interface approach is used when some type BaseRestreither directly or indirectly restricts BaseType. In that case, it is inconvenient to have class BaseRestrbe a subclass of BaseType(because it may have a very different content model.) Yet, in order to support type substitution, we still need to somehow represent the type hierarchy in the target language. This is accomplished using special "derivation interfaces", such as BaseType_derivations.

When the -noderiv option is chosen, the "derivation interfaces" will not be generated or implemented, and type substitution is not supported. If type Ris a restriction of type B, their corresponding classes will have no relationship to each other.

Thus, there are two forms for a class that is a base type for some other type. The first does not involve any interfaces:

   //-noderiv was used or there are no subtypes that are restrictions ofBaseType
   public class BaseType
   {
      ...
      /**
       * Factory method
       */
      public staticBaseType createObject(QName type) {...}
      ...
   }

In the second form, an interface is implemented:

Java:

   // -noderiv was not used and there is a subtype that is a restriction 
   // of BaseType
   public class BaseType implements BaseType_derivations
   {
      ...
      /**
       * Factory method
       */
      public static BaseType_derivations createObject(QName type) {...}
      ...
   }

C#:

   // -noderiv was not used and there is a subtype that is a restriction 
   // of BaseType
   public class BaseType : BaseType_derivations
   {
      ...
      /**
       * Factory method
       */
      public static BaseType_derivations createObject(QName type) {...}
      ...
   }

The factory method is used during decoding to create the correct class of object, based on the xsi:type attribute that was present.

There are likewise two forms for a derivations interface. If BaseTypeis at the root of the type hierarchy, it's derivations interface will be as follows:

Java:

   public interface BaseType_derivations
   {
      public void decode(XMLStreamReader] reader, XBContext xbContext, 
         boolean isNilled, boolean hasDefault) ;

      public void encode(XBXmlEncoder encoder, XBContext xbContext, 
         QName elemDeclType, boolean ignoreContent) ;
   }

C#:

   public interface BaseType_derivations
   {
      void decode(XmlTextReader reader, XBContext xbContext, 
         bool isNilled, bool hasDefault) ;

      void encode(XBXmlEncoder encoder, XBContext xbContext, 
         XBQualifiedName elemDeclType, bool ignoreContent) ;
   }

Additionally, if BaseType2is a direct extension/restriction of BaseType, and some other type restricts BaseType2(so that a derivations interface must also be generated for BaseType2), then we have:

Java:

   public interface BaseType2_derivations extends BaseType_derivations
   {
   }

C#:

   public interface BaseType2_derivations : BaseType_derivations
   {
   }

If you have an reference to one of the _derivations interfaces, you can use the is operator (C#) or the instanceof operator (Java) to determine what the actual type is.

Extension

When a type is extended with extension, the new type may add attributes or append a group of elements. XBinder models this by generating a class that extends the class generated for the original type.

XSD type:

   <xsd:complexType name="TypeName">
      <xsd:complexContent>
         <xsd:extension base="BaseType">
            <xsd:group[5]>
               <xsd:element name="elem1" type="Type1"/>
               <xsd:element name="elem2" type="Type2"/>
               ...
               <xsd:element name="elemN" type="TypeN"/>
            </xsd:group>
            <xsd:attribute name="attr1" type="Type1"/>
            <xsd:attribute name="attr2" type="Type2"/>
            ...
            <xsd:attribute name="attrN" type="TypeN"/>
         </xsd:extension>
      </xsd:complexContent>
   </xsd:complexType>

Generated Java:

   public class TypeName extends BaseType
   {
      ...
      [methods for properties for attributes attr1..attrN]
      [methods for properties for elements elem1..elemN]
      ...
   }

Generated C#:

   public class TypeName : BaseType
   {
      ...
      [methods for properties for attributes attr1..attrN]
      [methods for properties for elements elem1..elemN]
      ...
   }

Restriction

It is possible to restrict elements and attributes in an existing content model group by using the restrictionelement. For either elements or attributes, it is possible to exclude optional items from the derived content model. It is also possible to restrict wildcards ( anyor anyAttribute) to contain values of a given type. It is also possible to further restrict facets such as minOccursand maxOccursto specify a narrower range than was defined in the base type.

For C# and Java, the class generated for a restriction is the same as would have been generated for an equivalent XSD type defined without restriction. Any attribute or elements that are inherited from the base type are generated into the restricted type's class.

Assuming -noderiv was not used, the generated class will implement the derivations interface for the restricted type's supertype.

The general mapping is as follows:

XSD:

   <xsd:complexType name="TypeName">
      <xsd:complexContent>
         <xsd:restriction base="BaseType">
            ...
         </xsd:restriction>
      </xsd:complexContent>
   </xsd:complexType>

Generated Java:

   public class TypeName extends XBComplexTypeimplements BaseType_derivations
   {...}

Generated C#:

   public class TypeName : XBComplexType, BaseType_derivations
   {...}

anyType

XSD type anyTypeis a complex type with mixed content, which is the ultimate base type for all complex types. XBinder represents anyTypeby generating a class called AnyType:

Java:

   public class AnyType extends XBComplexType
   {
      ...
      //attribute methods for attribute wildcard

      public List<XBAttributeBase> getAnyAttr() {...}

      public boolean isSetAnyAttr() {...}

      public void unsetAnyAttr() {...}

      //content methods for mixed content model
      public String getMixedContent() {...}

      public boolean isSetMixedContent() {...}

      public void setMixedContent(String value) {...}
      ...
   }

C#:

   public class AnyType : XBComplexType
   {
      ...
      //attribute methods for attribute wildcard

      public IList<XBAttributeBase> getAnyAttr() {...}

      public bool isSetAnyAttr() {...}

      public void unsetAnyAttr() {...}

      //content methods for mixed content model
      public String getMixedContent() {...}

      public bool isSetMixedContent() {...}

      public void setMixedContent(String value) {...}
      ...
   }

Class AnyTypeis used wherever anyTypeis referenced: if an element is declared to be of type anyType, class AnyTypeis used; if a complex type is defined as an extension of anyType, the generated class will extend class AnyType. Class AnyTypeis only generated when it is needed.

Regarding restriction on anyType, note that:

   <xsd:complexType name="MyType">
      <xsd:complexContent>
         <xsd:restriction base="xsd:anyType">
           XSD content group definition...
         </xsd:restriction>
      </xsd:complexContent>
   <xsd:complexType>

is equivalent to:

   <xsd:complexType name="MyType">
      XSD content group definition...
   </xsd:complexType>

Therefore, a restriction on anyType is handled as a normal complex type definition, as discussed elsewhere.



[5] This may be "sequence" or "choice". A group reference may also be used, but it should refer to a sequence or choice group.