How do we define complex elements in XML Schema?

<book>
<title>Yunus Emre Divani</title>
<language>Turkish</language>
</book>

There are two common ways to define complex elements.

<xs:element name="book">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="title" type="xs:string"/>
      <xs:element name="language" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

In the first method, we define the complex type directly inside the element.

If the structure is unique to that element and will not be reused elsewhere, this approach is fine.

If the same structure will be used by multiple elements, I recommend the second method:

<xs:element name="book" type="bookEntry"/>
<xs:element name="aboutBook" type="bookEntry"/>
<!-- You can define for one or more elements. -->
  <xs:complexType name="bookEntry">
    <xs:sequence>
      <xs:element name="title" type="xs:string"/>
      <xs:element name="language" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

You can also extend a complex type with the properties of another type. From this point on, I will generally use the second method in the examples.

<xs:element name="book" type="bookEntry"/>
<xs:element name="aboutBook" type="aboutBook"/>
<!-- You can define for one or more elements. -->
  <xs:complexType name="bookEntry">
    <xs:sequence>
      <xs:element name="title" type="xs:string"/>
      <xs:element name="language" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

<xs:complexType name="aboutBook">
  <xs:complexContent>
    <xs:extension base="bookEntry">
      <xs:sequence>
        <xs:element name="author" type="xs:string"/>
        <xs:element name="isbn" type="xs:string"/>
      </xs:sequence>
    </xs:extension>
  </xs:complexContent>
</xs:complexType>

Empty Elements

<book isbn="9759954949"/>

To define this as a complex element:

<xs:element name="book" type="bookEntry"/>

<xs:complexType name="bookEntry">
  <xs:attribute name="isbn" type="xs:positiveInteger"/>
</xs:complexType>

This defines an empty book element with only an isbn attribute.

Element Only

<book>
  <title>Yunus Emre Divani</title>
  <language>Turkish</language>
</book>

For this XML example, the complex type definition looks like this:

<xs:element name="book" type="bookStructure"/>

<xs:complexType name="bookStructure">
  <xs:sequence>
    <xs:element name="title" type="xs:string"/>
    <xs:element name="language" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

Text Content Only

<book isbn="9759954949">Yunus Emre Divani</book>

To define a book element that contains text and also has an attribute:

<xs:element name="book" type="bookStructure"/>

<xs:complexType name="bookStructure">
  <xs:simpleContent>
    <xs:extension base="xs:string">
      <xs:attribute name="isbn" type="xs:positiveInteger" />
    </xs:extension>
  </xs:simpleContent>
</xs:complexType>

Mixed Content

<book>
  Book Title: <title>Yunus Emre Divani</title>
  Language: <language>Turkish</language>
  ISBN: <isbn>9759954949</isbn>
</book>

For elements with mixed content, define the complex type as follows:

<xs:element name="book" type="bookStructure"/>

<xs:complexType mixed="true" name="bookStructure">
  <xs:sequence>
    <xs:element name="title" type="xs:string"/>
    <xs:element name="language" type="xs:string"/>
    <xs:element name="isbn" type="xs:positiveInteger"/>
  </xs:sequence>
</xs:complexType>

Indicators

<all> allows child elements to appear in any order. Each child can appear at most once unless occurrence rules are defined.

<xs:complexType mixed="true" name="bookStructure">
  <xs:all>
    <xs:element name="title" type="xs:string"/>
    <xs:element name="language" type="xs:string"/>
    <xs:element name="isbn" type="xs:positiveInteger"/>
  </xs:all>
</xs:complexType>

<choice> allows one of the listed child elements to be used.

<xs:complexType mixed="true" name="bookStructure">
  <xs:choice>
    <xs:element name="title" type="xs:string"/>
    <xs:element name="language" type="xs:string"/>
    <xs:element name="isbn" type="xs:positiveInteger"/>
  </xs:choice>
</xs:complexType>

<sequence> requires child elements to appear in the specified order.

<xs:complexType mixed="true" name="bookStructure">
  <xs:sequence>
    <xs:element name="title" type="xs:string"/>
    <xs:element name="language" type="xs:string"/>
    <xs:element name="isbn" type="xs:positiveInteger"/>
  </xs:sequence>
</xs:complexType>

<maxOccurs> determines the maximum number of times a child element can appear. <minOccurs> determines the minimum number of times a child element must appear.

<xs:complexType mixed="true" name="bookStructure">
  <xs:sequence>
    <xs:element name="title" type="xs:string"/>
    <xs:element name="language" type="xs:string" maxOccurs="10" minOccurs="1"/>
  </xs:sequence>
</xs:complexType>

In the example above, the language element must appear at least once and can appear at most 10 times.

With <group>, you can create a reusable group and use it in multiple elements. You can also use the indicators above inside a group.

<xs:group name="bookGroup">
  <xs:sequence>
    <xs:element name="title" type="xs:string"/>
    <xs:element name="language" type="xs:string"/>
  </xs:sequence>
</xs:group>

<xs:element name="book" type="bookEntry"/>

<xs:complexType name="bookEntry">
  <xs:sequence>
    <xs:group ref="bookGroup"/>
    <xs:element name="isbn" type="xs:positiveInteger"/>
  </xs:sequence>
</xs:complexType>

The same idea applies to <attributeGroup>:

<xs:attributeGroup name="bookAttribute">
  <xs:attribute name="isbn" type="xs:positiveInteger"/>
</xs:attributeGroup>

<xs:element name="book" type="bookEntry"/>

<xs:complexType name="bookEntry">
  <xs:sequence>
    <xs:element name="title" type="xs:string"/>
    <xs:element name="language" type="xs:string"/>
  </xs:sequence>
  <xs:attributeGroup ref="bookAttribute"/>
</xs:complexType>

<any> is used to allow extension elements. In the example below, another element can be added after the defined fields.

<xs:complexType name="bookStructure">
  <xs:sequence>
    <xs:element name="title" type="xs:string"/>
    <xs:element name="language" type="xs:string"/>
    <xs:any minOccurs="0"/>
  </xs:sequence>
</xs:complexType>

<anyAttribute> is used to allow additional attributes.

<xs:complexType name="bookStructure">
  <xs:sequence>
    <xs:element name="title" type="xs:string"/>
    <xs:element name="language" type="xs:string"/>
  </xs:sequence>
  <xs:anyAttribute/>
</xs:complexType>

substitutionGroup lets one element substitute for another element.

<xs:element name="book" type="xs:string"/>
<xs:element name="title" substitutionGroup="book"/>
<!-- When defining XML -->
<book>Yunus Emre Divani</book>
<!-- or -->
<title>Yunus Emre Divani</title>

This lets us use either element in the XML. If we add block="substitution" as an attribute, the <title></title> form shown above is no longer allowed.

Data Types

Now let's look at XML Schema data types.

Text Data Types

Data TypeDescription
ENTITIESA list of entity references
ENTITYAn entity reference
IDA unique ID value assigned to an element
IDREFA reference to another element's ID
IDREFSA list of ID references
languageA valid language identifier
NameA valid XML name
NCNameAn XML name without a namespace prefix
NMTOKENA valid XML name token
NMTOKENSA list of XML name tokens
normalizedStringText with normalized line breaks and tabs
QNameA qualified XML name
stringText
tokenText with collapsed whitespace

Date Data Types

Data TypeDescription
dateDate data
dateTimeDate and time data
durationInterval data
gDayDay (DD)
gMonthMonth (MM)
gMonthDayMonth - Day (MM-DD)
gYearYear (YYYY)
gYearMonthYear - Month (YYYY-MM)
timeTime

Numeric Data Types

Data TypeDescription
bytesigned 8-bit integer
decimaldecimal value
intsigned 32-bit integer
integerinteger value
longsigned 64-bit integer
negativeIntegerNegative values (..,-2,-1)
nonNegativeIntegerNon-negative values (0,1,2,..)
nonPositiveIntegerNon-positive values (..,-2,-1,0)
positiveIntegerPositive values (1,2,..)
shortsigned 16-bit integer
unsignedLongunsigned 64-bit integer
unsignedIntunsigned 32-bit integer
unsignedShortunsigned 16-bit integer
unsignedByteunsigned 8-bit integer

Miscellaneous Data Types

Data TypeDescription
anyURIURI value
base64BinaryBase64-encoded binary data
booleanTrue or false value
doubleDouble-precision floating-point number
floatFloating-point number
hexBinaryHexadecimal binary data
NOTATIONNotation declared in the schema
QNameQualified XML name