XML Schema Complex Types

Defining complex type elements

A complex element contains other elements and/or attributes.

What is a Complex Element?

A complex element is an XML element that contains other elements and/or attributes.

There are four kinds of complex elements:

  • empty elements
  • elements that contain only other elements
  • elements that contain only text
  • elements that contain both other elements and text

Note: Each of these elements may contain attributes as well!


Examples of Complex Elements

A complex XML element, “product”, which is empty:<product pid=”1345″/>

A complex XML element, “employee”, which contains only other elements:<employee>
  <firstname>John</firstname>
  <lastname>Smith</lastname>
</employee>

A complex XML element, “food”, which contains only text:<food type=”dessert”>Ice cream</food>

A complex XML element, “description”, which contains both elements and text:<description>
It happened on <date lang=”norwegian”>03.03.99</date> ….
</description>

How to Define a Complex Element

Look at this complex XML element, “employee”, which contains only other elements:<employee>
  <firstname>John</firstname>
  <lastname>Smith</lastname>
</employee>

We can define a complex element in an XML Schema two different ways:

1. The “employee” element can be declared directly by naming the element, like this:<xs:element name=”employee”>
  <xs:complexType>
    <xs:sequence>
      <xs:element name=”firstname” type=”xs:string”/>
      <xs:element name=”lastname” type=”xs:string”/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

If you use the method described above, only the “employee” element can use the specified complex type. Note that the child elements, “firstname” and “lastname”, are surrounded by the <sequence> indicator. This means that the child elements must appear in the same order as they are declared. You will learn more about indicators in the XSD Indicators chapter.

2. The “employee” element can have a type attribute that refers to the name of the complex type to use:<xs:element name=”employee” type=”personinfo”/>

<xs:complexType name=”personinfo”>
  <xs:sequence>
    <xs:element name=”firstname” type=”xs:string”/>
    <xs:element name=”lastname” type=”xs:string”/>
  </xs:sequence>
</xs:complexType>

If you use the method described above, several elements can refer to the same complex type, like this:<xs:element name=”employee” type=”personinfo”/>
<xs:element name=”student” type=”personinfo”/>
<xs:element name=”member” type=”personinfo”/>

<xs:complexType name=”personinfo”>
  <xs:sequence>
    <xs:element name=”firstname” type=”xs:string”/>
    <xs:element name=”lastname” type=”xs:string”/>
  </xs:sequence>
</xs:complexType>

You can also base a complex element on an existing complex element and add some elements, like this:<xs:element name=”employee” type=”fullpersoninfo”/>

<xs:complexType name=”personinfo”>
  <xs:sequence>
    <xs:element name=”firstname” type=”xs:string”/>
    <xs:element name=”lastname” type=”xs:string”/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name=”fullpersoninfo”>
  <xs:complexContent>
    <xs:extension base=”personinfo”>
      <xs:sequence>
        <xs:element name=”address” type=”xs:string”/>
        <xs:element name=”city” type=”xs:string”/>
        <xs:element name=”country” type=”xs:string”/>
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

An empty complex element cannot have contents, only attributes.


Complex Empty Elements

An empty XML element:<product prodid=”1345″ />

The “product” element above has no content at all. To define a type with no content, we must define a type that allows elements in its content, but we do not actually declare any elements, like this:<xs:element name=”product”>
  <xs:complexType>
    <xs:complexContent>
      <xs:restriction base=”xs:integer”>
        <xs:attribute name=”prodid” type=”xs:positiveInteger”/>
      </xs:restriction>
    </xs:complexContent>
  </xs:complexType>
</xs:element>

In the example above, we define a complex type with a complex content. The complexContent element signals that we intend to restrict or extend the content model of a complex type, and the restriction of integer declares one attribute but does not introduce any element content.

However, it is possible to declare the “product” element more compactly, like this:<xs:element name=”product”>
  <xs:complexType>
    <xs:attribute name=”prodid” type=”xs:positiveInteger”/>
  </xs:complexType>
</xs:element>

Or you can give the complexType element a name, and let the “product” element have a type attribute that refers to the name of the complexType (if you use this method, several elements can refer to the same complex type):<xs:element name=”product” type=”prodtype”/>

<xs:complexType name=”prodtype”>
  <xs:attribute name=”prodid” type=”xs:positiveInteger”/>
</xs:complexType>

Mixed Content elements

A mixed complex type element can contain attributes, elements, and text.


Complex Types with Mixed Content

An XML element, “letter”, that contains both text and other elements:<letter>
  Dear Mr. <name>John Smith</name>.
  Your order <orderid>1032</orderid>
  will be shipped on <shipdate>2001-07-13</shipdate>.
</letter>

The following schema declares the “letter” element:<xs:element name=”letter”>
  <xs:complexType mixed=”true”>
    <xs:sequence>
      <xs:element name=”name” type=”xs:string”/>
      <xs:element name=”orderid” type=”xs:positiveInteger”/>
      <xs:element name=”shipdate” type=”xs:date”/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

Note: To enable character data to appear between the child-elements of “letter”, the mixed attribute must be set to “true”. The <xs:sequence> tag means that the elements defined (name, orderid and shipdate) must appear in that order inside a “letter” element.

We could also give the complexType element a name, and let the “letter” element have a type attribute that refers to the name of the complexType (if you use this method, several elements can refer to the same complex type):<xs:element name=”letter” type=”lettertype”/>

<xs:complexType name=”lettertype” mixed=”true”>
  <xs:sequence>
    <xs:element name=”name” type=”xs:string”/>
    <xs:element name=”orderid” type=”xs:positiveInteger”/>
    <xs:element name=”shipdate” type=”xs:date”/>
  </xs:sequence>
</xs:complexType>

Grouping Attributes

The <anyAttribute> element enables us to extend the XML document with attributes not specified by the schema!


The <anyAttribute> Element

The <anyAttribute> element enables us to extend the XML document with attributes not specified by the schema.

The following example is a fragment from an XML schema called “family.xsd”. It shows a declaration for the “person” element. By using the <anyAttribute> element we can add any number of attributes to the “person” element:<xs:element name=”person”>
  <xs:complexType>
    <xs:sequence>
      <xs:element name=”firstname” type=”xs:string”/>
      <xs:element name=”lastname” type=”xs:string”/>
    </xs:sequence>
    <xs:anyAttribute/>
  </xs:complexType>
</xs:element>

Now we want to extend the “person” element with a “eyecolor” attribute. In this case we can do so, even if the author of the schema above never declared any “eyecolor” attribute.

Look at this schema file, called “attribute.xsd”:<?xml version=”1.0″ encoding=”UTF-8″?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”
targetNamespace=”https://www.w3schools.com”
xmlns=”https://www.w3schools.com”
elementFormDefault=”qualified”>

<xs:attribute name=”eyecolor”>
  <xs:simpleType>
    <xs:restriction base=”xs:string”>
      <xs:pattern value=”blue|brown|green|grey”/>
    </xs:restriction>
  </xs:simpleType>
</xs:attribute>

</xs:schema>

The XML file below (called “Myfamily.xml”), uses components from two different schemas; “family.xsd” and “attribute.xsd”:<?xml version=”1.0″ encoding=”UTF-8″?>

<persons xmlns=”http://www.microsoft.com”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:SchemaLocation=”http://www.microsoft.com family.xsd
https://www.w3schools.com attribute.xsd”>

<person eyecolor=”green”>
  <firstname>Hege</firstname>
  <lastname>Refsnes</lastname>
</person>

<person eyecolor=”blue”>
  <firstname>Stale</firstname>
  <lastname>Refsnes</lastname>
</person>

</persons>

The XML file above is valid because the schema “family.xsd” allows us to add an attribute to the “person” element.

The <any> and <anyAttribute> elements are used to make EXTENSIBLE documents! They allow documents to contain additional elements that are not declared in the main XML schema.