-
Language:
English
-
Language:
English
Red Hat Training
A Red Hat training course is available for Red Hat Fuse
3.4. Defining complex data types
XML Schema provides a flexible and powerful mechanism for building complex data structures from its simple data types. You can create data structures by creating a sequence of elements and attributes. You can also extend your defined types to create even more complex types.
In addition to building complex data structures, you can also describe specialized types such as enumerated types, data types that have a specific range of values, or data types that need to follow certain patterns by either extending or restricting the primitive types.
3.4.1. Defining data structures
In XML Schema, data units that are a collection of data fields are defined using
complexType elements. Specifying a complex type requires three pieces of information:
- The name of the defined type is specified in the
nameattribute of thecomplexTypeelement. - The first child element of the
complexTypedescribes the behavior of the structure’s fields when it is put on the wire. See the section called “Complex type varieties”. - Each of the fields of the defined structure are defined in
elementelements that are grandchildren of thecomplexTypeelement. See the section called “Defining the parts of a structure”.
For example, the structure shown in Example 3.3, “Simple Structure” is be defined in XML Schema as a complex type with two elements.
Example 3.3. Simple Structure
struct personalInfo
{
string name;
int age;
};
Example 3.4, “A complex type” shows one possible XML Schema mapping for the structure shown in Example 3.3, “Simple Structure”.
Example 3.4. A complex type
<complexType name="personalInfo">
<sequence>
<element name="name" type="xsd:string" />
<element name="age" type="xsd:int" />
</sequence>
</complexType>Complex type varieties
XML Schema has three ways of describing how the fields of a complex type are organized when represented as an XML document and passed on the wire. The first child element of the
complexType element determines which variety of complex type is being used. Table 3.1, “Complex type descriptor elements” shows the elements used to define complex type behavior.
Table 3.1. Complex type descriptor elements
If a
sequence element, an all element, or a choice is not specified, then a sequence is assumed. For example, the structure defined in Example 3.4, “A complex type” generates a message containing two elements: name and age.
If the structure is defined using a
choice element, as shown in Example 3.5, “Simple complex choice type”, it generates a message with either a name element or an age element.
Example 3.5. Simple complex choice type
<complexType name="personalInfo">
<choice>
<element name="name" type="xsd:string"/>
<element name="age" type="xsd:int"/>
</choice>
</complexType>Defining the parts of a structure
You define the data fields that make up a structure using
element elements. Every complexType element should contain at least one element element. Each element element in the complexType element represents a field in the defined data structure.
To fully describe a field in a data structure,
element elements have two required attributes:
In addition to
name and type, element elements have two other commonly used optional attributes: minOcurrs and maxOccurs. These attributes place bounds on the number of times the field occurs in the structure. By default, each field occurs only once in a complex type. Using these attributes, you can change how many times a field must or can appear in a structure. For example, you can define a field, previousJobs, that must occur at least three times, and no more than seven times, as shown in Example 3.6, “Simple complex type with occurrence constraints”.
Example 3.6. Simple complex type with occurrence constraints
<complexType name="personalInfo>
<all>
<element name="name" type="xsd:string"/>
<element name="age" type="xsd:int"/>
<element name="previousJobs" type="xsd:string:
minOccurs="3" maxOccurs="7"/>
</all>
</complexType>
You can also use the
minOccurs to make the age field optional by setting the minOccurs to zero as shown in Example 3.7, “Simple complex type with minOccurs set to zero”. In this case age can be omitted and the data will still be valid.
Example 3.7. Simple complex type with minOccurs set to zero
<complexType name="personalInfo>
<choice>
<element name="name" type="xsd:string"/>
<element name="age" type="xsd:int" minOccurs="0"/>
</choice>
</complexType>Defining attributes
In XML documents attributes are contained in the element’s tag. For example, in the
complexType element name is an attribute. They are specified using the attribute element. It comes after the all, sequence, or choice element and are a direct child of the complexType element. Example 3.8, “Complex type with an attribute” shows a complex type with an attribute.
Example 3.8. Complex type with an attribute
<complexType name="personalInfo>
<all>
<element name="name" type="xsd:string"/>
<element name="previousJobs" type="xsd:string"
minOccurs="3" maxOccurs="7"/>
</all>
<attribute name="age" type="xsd:int" use="optional" />
</complexType>
The
attribute element has three attributes:
If you specify that the attribute is optional you can add the optional attribute
default. The default attribute allows you to specify a default value for the attribute.
3.4.2. Defining arrays
Apache CXF supports two methods for defining arrays in a contract. The first is define a complex type with a single element whose
maxOccurs attribute has a value greater than one. The second is to use SOAP arrays. SOAP arrays provide added functionality such as the ability to easily define multi-dimensional arrays and to transmit sparsely populated arrays.
Complex type arrays
Complex type arrays are a special case of a sequence complex type. You simply define a complex type with a single element and specify a value for the
maxOccurs attribute. For example, to define an array of twenty floating point numbers you use a complex type similar to the one shown in Example 3.9, “Complex type array”.
Example 3.9. Complex type array
<complexType name="personalInfo"> <element name="averages" type="xsd:float" maxOccurs="20"/> </complexType>
You can also specify a value for the
minOccurs attribute.
SOAP arrays
SOAP arrays are defined by deriving from the SOAP-ENC:Array base type using the
wsdl:arrayType element. The syntax for this is shown in Example 3.10, “Syntax for a SOAP array derived using wsdl:arrayType”.
Example 3.10. Syntax for a SOAP array derived using wsdl:arrayType
<complexType name="TypeName">
<complexContent>
<restriction base="SOAP-ENC:Array">
<attribute ref="SOAP-ENC:arrayType"
wsdl:arrayType="ElementType<ArrayBounds>"/>
</restriction>
</complexContent>
</complexType>
Using this syntax, TypeName specifies the name of the newly-defined array type. ElementType specifies the type of the elements in the array. ArrayBounds specifies the number of dimensions in the array. To specify a single dimension array use
[]; to specify a two-dimensional array use either [][] or [,].
For example, the SOAP Array, SOAPStrings, shown in Example 3.11, “Definition of a SOAP array”, defines a one-dimensional array of strings. The
wsdl:arrayType attribute specifies the type of the array elements, xsd:string, and the number of dimensions, with [] implying one dimension.
Example 3.11. Definition of a SOAP array
<complexType name="SOAPStrings">
<complexContent>
<restriction base="SOAP-ENC:Array">
<attribute ref="SOAP-ENC:arrayType"
wsdl:arrayType="xsd:string[]"/>
</restriction>
</complexContent>
</complexType>
You can also describe a SOAP Array using a simple element as described in the SOAP 1.1 specification. The syntax for this is shown in Example 3.12, “Syntax for a SOAP array derived using an element”.
Example 3.12. Syntax for a SOAP array derived using an element
<complexType name="TypeName">
<complexContent>
<restriction base="SOAP-ENC:Array">
<sequence>
<element name="ElementName" type="ElementType"
maxOccurs="unbounded"/>
</sequence>
</restriction>
</complexContent>
</complexType>
When using this syntax, the element's
maxOccurs attribute must always be set to unbounded.
3.4.3. Defining types by extension
Like most major coding languages, XML Schema allows you to create data types that inherit some of their elements from other data types. This is called defining a type by extension. For example, you could create a new type called
alienInfo, that extends the personalInfo structure defined in Example 3.4, “A complex type” by adding a new element called planet.
Types defined by extension have four parts:
- The name of the type is defined by the
nameattribute of thecomplexTypeelement. - The
complexContentelement specifies that the new type will have more than one element.NoteIf you are only adding new attributes to the complex type, you can use asimpleContentelement. - The type from which the new type is derived, called the base type, is specified in the
baseattribute of theextensionelement. - The new type’s elements and attributes are defined in the
extensionelement, the same as they are for a regular complex type.
For example,
alienInfo is defined as shown in Example 3.13, “Type defined by extension”.
Example 3.13. Type defined by extension
<complexType name="alienInfo">
<complexContent>
<extension base="personalInfo">
<sequence>
<element name="planet" type="xsd:string"/>
</sequence>
</extension>
</complexContent>
</complexType>3.4.4. Defining types by restriction
XML Schema allows you to create new types by restricting the possible values of an XML Schema simple type. For example, you can define a simple type,
SSN, which is a string of exactly nine characters. New types defined by restricting simple types are defined using a simpleType element.
The definition of a type by restriction requires three things:
- The name of the new type is specified by the
nameattribute of thesimpleTypeelement. - The simple type from which the new type is derived, called the base type, is specified in the
restrictionelement. See the section called “Specifying the base type”. - The rules, called facets, defining the restrictions placed on the base type are defined as children of the
restrictionelement. See the section called “Defining the restrictions”.
Specifying the base type
The base type is the type that is being restricted to define the new type. It is specified using a
restriction element. The restriction element is the only child of a simpleType element and has one attribute, base, that specifies the base type. The base type can be any of the XML Schema simple types.
For example, to define a new type by restricting the values of an xsd:int you use a definition like the one shown in Example 3.14, “Using int as the base type”.
Example 3.14. Using int as the base type
<simpleType name="restrictedInt">
<restriction base="xsd:int">
...
</restriction>
</simpleType>Defining the restrictions
The rules defining the restrictions placed on the base type are called facets. Facets are elements with one attribute,
value, that defines how the facet is enforced. The available facets and their valid value settings depend on the base type. For example, xsd:string supports six facets, including:
lengthminLengthmaxLengthpatternwhitespaceenumeration
Each facet element is a child of the
restriction element.
Example
Example 3.15, “SSN simple type description” shows an example of a simple type,
SSN, which represents a social security number. The resulting type is a string of the form xxx-xx-xxxx. <SSN>032-43-9876<SSN> is a valid value for an element of this type, but <SSN>032439876</SSN> is not.
Example 3.15. SSN simple type description
<simpleType name="SSN">
<restriction base="xsd:string">
<pattern value="\d{3}-\d{2}-\d{4}"/>
</restriction>
</simpleType>3.4.5. Defining enumerated types
Enumerated types in XML Schema are a special case of definition by restriction. They are described by using the
enumeration facet which is supported by all XML Schema primitive types. As with enumerated types in most modern programming languages, a variable of this type can only have one of the specified values.
Defining an enumeration in XML Schema
The syntax for defining an enumeration is shown in Example 3.16, “Syntax for an enumeration”.
Example 3.16. Syntax for an enumeration
<simpleType name="EnumName">
<restriction base="EnumType">
<enumeration value="Case1Value"/>
<enumeration value="Case2Value"/>
...
<enumeration value="CaseNValue"/>
</restriction>
</simpleType>
EnumName specifies the name of the enumeration type. EnumType specifies the type of the case values. CaseNValue, where N is any number one or greater, specifies the value for each specific case of the enumeration. An enumerated type can have any number of case values, but because it is derived from a simple type, only one of the case values is valid at a time.
Example
For example, an XML document with an element defined by the enumeration
widgetSize, shown in Example 3.17, “widgetSize enumeration”, would be valid if it contained <widgetSize>big</widgetSize>, but it would not be valid if it contained <widgetSize>big,mungo</widgetSize>.
Example 3.17. widgetSize enumeration
<simpleType name="widgetSize">
<restriction base="xsd:string">
<enumeration value="big"/>
<enumeration value="large"/>
<enumeration value="mungo"/>
</restriction>
</simpleType>