Complex-Type Elements

In this lesson of the XML Schema tutorial, you will learn...
  1. To declare complex-type elements.
  2. To use content models.
  3. To control cardinality (quantity of elements).
  4. To declare elements of mixed types.
  5. To define named complex types.

Overview

Complex-type elements have attributes, child elements, or some combination of the two. For example, the Name and HomePage elements below are both complex-type elements.

Code Sample: ComplexTypes/Demos/ComplexType.xml

<?xml version="1.0"?>
<Person>
 <Name>
  <FirstName>Mark</FirstName>
  <LastName>Twain</LastName>
 </Name>
 <HomePage URL="http://www.marktwain.com"/>
</Person>

As the diagram below shows, a complex-type element can be empty, contain simple content such as a string, or can contain complex content such as a sequence of elements.

Whereas it is not necessary to explicitly declare that a simple-type element is a simple type, it is necessary to specify that a complex-type element is a complex type. This is done with the xs:complexType element as shown below.

Syntax
<xs:element name="ElementName">
 <xs:complexType>
  <!--Content Model Goes Here-->
 </xs:complexType>
</xs:element>

Content Models

Content models are used to indicate the structure and order in which child elements can appear within their parent element. Content models are made up of model groups. The three types of model groups are listed below.

  1. xs:sequence - the elements must appear in the order specified.
  2. xs:all - the elements must appear, but order is not important.
  3. xs:choice - only one of the elements can appear.

xs:sequence

The following sample shows the syntax for declaring a complex-type element as a sequence, meaning that the elements must show up in the order they are declared.

Syntax
<xs:element name="ElementName">
 <xs:complexType>
  <xs:sequence>
   <xs:element name="Child1" type="xs:string"/>
   <xs:element name="Child2" type="xs:string"/>
   <xs:element name="Child3" type="xs:string"/>
  </xs:sequence>
 </xs:complexType>
</xs:element>

xs:all

The following sample shows the syntax for declaring a complex-type element as a conjunction, meaning that the elements can show up in any order.

Syntax
<xs:element name="ElementName">
 <xs:complexType>
  <xs:all>
   <xs:element name="Child1" type="xs:string"/>
   <xs:element name="Child2" type="xs:string"/>
   <xs:element name="Child3" type="xs:string"/>
  </xs:all>
 </xs:complexType>
</xs:element>

xs:choice

The following sample shows the syntax for declaring a complex-type element as a choice, meaning that only one of the child elements may show up.

Syntax
<xs:element name="ElementName">
 <xs:complexType>
  <xs:choice>
   <xs:element name="Child1" type="xs:string"/>
   <xs:element name="Child2" type="xs:string"/>
   <xs:element name="Child3" type="xs:string"/>
  </xs:choice>
 </xs:complexType>
</xs:element>

Complex Model Groups

In the examples above, the model groups are all made up of simple-type elements. However, complex-type elements can contain other complex-type elements.

Syntax
<xs:element name="ElementName">
 <xs:complexType>
  <xs:choice>
   <xs:element name="Child1" type="xs:string"/>
   <xs:element name="Child2">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="GC1" type="xs:string"/>
      <xs:element name="GC2" type="xs:string"/>
     </xs:sequence>
    </xs:complexType>
   </xs:element>
   <xs:element name="Child3" type="xs:string"/>
  </xs:choice>
 </xs:complexType>
</xs:element>

Furthermore, model groups can be nested within each other. The following example illustrates this. Notice that the choice model group, which allows for either a Salary element or a Wage element is nested with in a sequence model group. Both of the subsequent instances are valid according to this schema.

Code Sample: ComplexTypes/Demos/Employee.xsd

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:simpleType name="Salary">
  <xs:restriction base="xs:decimal">
   <xs:minInclusive value="10000"/>
   <xs:maxInclusive value="90000"/>
  </xs:restriction>
 </xs:simpleType>
 <xs:element name="Employee">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="Name">
     <xs:complexType>
      <xs:sequence>
       <xs:element name="FirstName"/>
       <xs:element name="LastName"/>
      </xs:sequence>
     </xs:complexType>
    </xs:element>
    <xs:choice>
     <xs:element name="Salary" type="Salary"/>
     <xs:element name="Wage" type="xs:decimal"/>
    </xs:choice>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>

Code Sample: ComplexTypes/Demos/DaveSmith.xml

<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:noNamespaceSchemaLocation="Employee.xsd">
 <Name>
  <FirstName>Dave</FirstName>
  <LastName>Smith</LastName>
 </Name>
 <Salary>90000</Salary>
</Employee>

Code Sample: ComplexTypes/Demos/JillSmith.xml

<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:noNamespaceSchemaLocation="Employee.xsd">
 <Name>
  <FirstName>Jill</FirstName>
  <LastName>Smith</LastName>
 </Name>
 <Wage>20.50</Wage>
</Employee>

Occurrence Constraints

By default, elements that are declared locally must show up once and only once within their parent. This constraint can be changed using the minOccurs and maxOccurs attributes. The default value of each of these attributes is 1. The value of minOccurs can be any non-negative integer. The value of maxOccurs can be any positive integer or unbounded, meaning that the element can appear an infinite number of times.

The example below shows how minOccurs can be used to make an element optional and how maxOccurs can be used to allow an element to be repeated indefinitely.

Code Sample: ComplexTypes/Demos/Employee2.xsd

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:simpleType name="Salary">
  <xs:restriction base="xs:decimal">
   <xs:minInclusive value="10000"/>
   <xs:maxInclusive value="90000"/>
  </xs:restriction>
 </xs:simpleType>
 <xs:element name="Employee">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="Name">
     <xs:complexType>
      <xs:sequence>
       <xs:element name="FirstName"/>
       <xs:element name="MiddleName" minOccurs="0"/>
       <xs:element name="LastName"/>
      </xs:sequence>
     </xs:complexType>
    </xs:element>
    <xs:choice>
     <xs:element name="Salary" type="Salary"/>
     <xs:element name="Wage" type="xs:decimal"/>
    </xs:choice>
    <xs:element name="Responsibilities">
     <xs:complexType>
      <xs:sequence>
       <xs:element name="Responsibility" type="xs:string" 
        maxOccurs="unbounded"/>
      </xs:sequence>
     </xs:complexType>
    </xs:element>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>
Code Explanation

Note that minOccurs and maxOccurs can also be applied to model groups (e.g, xs:sequence) to control the number of times a model group can be repeated.

Declaring Global Complex-Type Elements

As with simple-type elements, complex-type elements can be declared globally by placing the element declaration as a child of the xs:schema element.

Globally declared elements cannot take occurrence constraints. However, the minOccurs and maxOccurs constraints can be applied to references to globally declared elements. To illustrate, look at the following example. Notice that all elements, both simple-type and complex-type, are declared globally and then referenced within the model groups. Some of the references (e.g, Responsibilities) have occurrence constraints assigned to them.

Code Sample: ComplexTypes/Demos/Employee3.xsd

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:simpleType name="Salary">
  <xs:restriction base="xs:decimal">
   <xs:minInclusive value="10000"/>
   <xs:maxInclusive value="90000"/>
  </xs:restriction>
 </xs:simpleType>
 <xs:element name="Name">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="FirstName"/>
    <xs:element ref="MiddleName" minOccurs="0"/>
    <xs:element ref="LastName"/>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 <xs:element name="FirstName"/>
 <xs:element name="MiddleName"/>
 <xs:element name="LastName"/>
 <xs:element name="Wage" type="xs:decimal"/>
 <xs:element name="Salary" type="Salary"/>
 <xs:element name="Responsibilities">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="Responsibility" maxOccurs="unbounded"/>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 <xs:element name="Responsibility" type="xs:string"/>
 <xs:element name="Employee">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="Name"/>
    <xs:choice>
     <xs:element ref="Salary"/>
     <xs:element ref="Wage"/>
    </xs:choice>
    <xs:element ref="Responsibilities" minOccurs="0"/>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>

Mixed Content

Sometimes an element will contain both child elements and character text. For example, a para element might contain mostly plain character text, but it could also have other elements (e.g, emphasis) littered throughout the character text.

As an example, let's examine look at the following XML instance document.

Code Sample: ComplexTypes/Demos/PaulMcCartney.xml

<?xml version="1.0"?>
<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:noNamespaceSchemaLocation="Employee4.xsd">
 <Name>
  <FirstName>Paul</FirstName>
  <LastName>McCartney</LastName>
 </Name>
 <Salary>90000</Salary>
 <Bio>
  Worked for <Company>the Beatles</Company> as a 
   <JobTitle>Singer</JobTitle>.
  Worked for <Company>the Beatles</Company> as a 
   <JobTitle>Bass Guitarist</JobTitle>.
  Worked for <Company>the Wings</Company> as a 
   <JobTitle>Singer</JobTitle>.
 </Bio>
</Employee>
Code Explanation

Notice that the Bio element contains child elements Company and JobTitle as well as character text. Such elements are said to contain mixed content. The syntax for declaring elements with mixed content is shown below.

Syntax
<xs:element name="ElementName">
 <xs:complexType mixed="true">
  <xs:sequence>
   <xs:element name="Child1" type="xs:string"/>
   <xs:element name="Child2" type="xs:string"/>
  </xs:sequence>
 </xs:complexType>
</xs:element>

The following example illustrates how to define this in our employee schema.

Code Sample: ComplexTypes/Demos/Employee4.xsd

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
---- Code Omitted ----
<xs:element name="Bio"> <xs:complexType mixed="true"> <xs:sequence maxOccurs="unbounded"> <xs:element name="Company" type="xs:string"/> <xs:element name="JobTitle" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element>
---- Code Omitted ----
</xs:schema>

Defining Complex Types Globally

As with simple types, complex types can be defined globally. The example below shows how this is done.

Code Sample: ComplexTypes/Demos/Author.xsd

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:complexType name="Person">
  <xs:sequence>
   <xs:element name="FirstName" type="xs:string"/>
   <xs:element name="LastName" type="xs:string"/>
  </xs:sequence>
 </xs:complexType>
 <xs:element name="Author" type="Person"/>
</xs:schema>
Code Explanation

As you can see, complex types are defined with the xs:complexType element. The major advantage of defining a complex type globally is that it can be reused. For example, a schema might allow for an Illustrator element as well as an Author element. Both elements could be of type Person. This way, if the Person type is changed later, the change will apply to both elements.

The instance document below will validate properly against the schema above.

Code Sample: ComplexTypes/Demos/MarkTwain.xml

<?xml version="1.0"?>
<Author xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:noNamespaceSchemaLocation="Author.xsd">
 <FirstName>Mark</FirstName>
 <LastName>Twain</LastName>
</Author>

Complex-Type Elements Conclusion

In this lesson of the XML Schema tutorial, you have learned to work with complex types and complex-type elements. We will now take a look at declaring attributes.

To continue to learn XML Schema go to the top of this page and click on the next lesson in this XML Schema Tutorial's Table of Contents.

Use of this website implies agreement to the following:

Copyright Information

All pages and graphics on this Web site are the property of Webucator, Inc. unless otherwise specified.

None of the content on this website may be redistributed or reproduced in any way, shape, or form without written permission from Webucator, Inc.

No Printing or saving of web pages

This content may not be printed or saved. It is for online use only.


Linking to this website

You may link to any of the pages on this website; however, you may not include the content in a frame or iframe without written permission from Webucator, Inc.


Warranties

This website is provided without warranty of any kind. There are no guarantees that use of the site will not be subject to interruptions. All direct or indirect risk related to use of the site is borne entirely by the user. All code and explanations provided on this site are provided without warranties to correctness, performance, fitness, merchantability, and/or any other warranty (whether expressed or implied).

For individual private use only

You agree not to use this online manual to deliver or receive training. If you are delivering or attending a class that is making use of this online manual, you are in violation of our terms of service. Please report any abuse to courseware@webucator.com. If you would like to deliver or receive training using this manual, please fill out the form at http://www.webucator.com/Contact.cfm.