XML Schema is a powerful alternative to XML DTD. The XML Schema language is commonly called XML Schema Definition, or XSD.

Why XML Schema?

  • It supports data types.
  • It is written with XML syntax.
  • It helps define safer data exchange contracts.
  • It is flexible.

The <schema> Element

The root element of an XSD document is the <schema> element.

<?xml version="1.0"?>
<xs:schema>
<!-- Code Block -->
</xs:schema>

The <schema> element can include attributes like these:

<?xml version="1.0"?>
<xs:schema
		xmlns:xs="http://www.w3.org/2001/XMLSchema"
		targetNamespace="https://example.com"
		xmlns="https://example.com">
<!-- Code Block -->
</xs:schema>

The xmlns:xs attribute says that XSD elements will come from the http://www.w3.org/2001/XMLSchema namespace.

The targetNamespace attribute defines the namespace for the elements and attributes described by this schema.

The xmlns attribute defines the default namespace for the XML document.

If we want an XML document to reference an XSD file:

<?xml version="1.0"?>
<books xmlns="http://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3schools.com https://example.com/books.xsd">
<!-- XML -->
</books>

The xsi:schemaLocation attribute maps the XML namespace to the XSD file that should be used for validation.

Simple Elements

Element Definition

To define XML elements with XSD:

<xs:element name="element-name" type="element-type"/>

Element Types:

  • xs:string
  • xs:decimal
  • xs:integer
  • xs:boolean
  • xs:date
  • xs:time

Let's apply these element types to our library example. Example XML:

<?xml version="1.0"?>
<book>
	<title>Yunus Emre Divani</title>
	<author>Selim Yagmur</author>
	<language>Turkish</language>
	<edition>8</edition>
	<date>2014-04-01</date>
</book>

Now let's define them with XSD:

<xs:element name="title" type="xs:string"/>
<xs:element name="author" type="xs:string"/>
<xs:element name="language" type="xs:string"/>
<xs:element name="edition" type="xs:integer"/>
<xs:element name="date" type="xs:date"/>

When defining XSD elements, use default for a default value and fixed for a value that must not change:

<xs:element name="language" type="xs:string" fixed="Turkish"/>
<xs:element name="edition" type="xs:integer" default="1"/>

Attribute Definition

To define attributes:

<xs:attribute name="attribute-name" type="attribute-type"/>

Attribute Types:

  • xs:string
  • xs:decimal
  • xs:integer
  • xs:boolean
  • xs:date
  • xs:time

Let's use the library example again. Example XML:

<?xml version="1.0"?>
<book isbn="9759954949">
	<author role="Editor">Selim Yagmur</author>
</book>

Let's define the attributes with XSD:

<xs:attribute name="isbn" type="xs:integer"/>
<xs:attribute name="role" type="xs:string"/>

Restrictions

The general structure for restricting element values is:

<xs:element name="element-name">
	<xs:simpleType>
		<xs:restriction base="element-type">
			<!-- Restrictions -->
		</xs:restriction>
	</xs:simpleType>
</xs:element>

To define the minimum and maximum allowed values for edition, use minInclusive and maxInclusive:

<xs:element name="edition">
	<xs:simpleType>
		<xs:restriction base="xs:integer">
			<xs:minInclusive value="1"/>
			<xs:maxInclusive value="500"/>
		</xs:restriction>
	</xs:simpleType>
</xs:element>

This restricts the edition element to values between 1 and 500.

<xs:element name="role">
	<xs:simpleType>
		<xs:restriction base="xs:string">
			<xs:enumeration value="author"/>
			<xs:enumeration value="translator"/>
			<xs:enumeration value="editor"/>
		</xs:restriction>
	</xs:simpleType>
</xs:element>

Here, we define three allowed options for the author's role. If you want to define a restriction once and reuse it in multiple places, create a named simple type:

<!-- When defining an element, use the restriction name as the type -->
<xs:element name="element-name" type="restriction-name"/>
<xs:simpleType name="restriction-name">
	 <xs:restriction base="xs:string">
			<!-- Restrictions -->
	 </xs:restriction>
</xs:simpleType>
<!-- Example -->
<xs:element name="role" type="roleRestriction"/>
<xs:simpleType name="roleRestriction">
	 <xs:restriction base="xs:string">
			<xs:enumeration value="author"/>
			<xs:enumeration value="translator"/>
			<xs:enumeration value="editor"/>
	 </xs:restriction>
</xs:simpleType>

You can also define patterns:

<xs:element name="element-name">
	<xs:simpleType>
		<xs:restriction base="xs:string">
			<xs:pattern value="pattern"/>
		</xs:restriction>
	</xs:simpleType>
</xs:element>

Let's define a pattern where the first character is lowercase and the others are uppercase:

<xs:element name="name">
	<xs:simpleType>
		<xs:restriction base="xs:string">
			<xs:pattern value="[a-z]([A-Z])*"/>
		</xs:restriction>
	</xs:simpleType>
</xs:element>

Patterns and their explanations:

<xs:element name="name">
	<xs:simpleType>
		<xs:restriction base="xs:string">
			<xs:pattern value="[a-z]"/> <!-- Single character and lowercase letters -->
			<xs:pattern value="[A-Z]"/> <!-- Single character and uppercase letters -->
			<xs:pattern value="[a-zA-Z]"/> <!-- Single character and lowercase or uppercase letters -->
			<xs:pattern value="[a-zA-Z][a-zA-Z]"/> <!-- Two characters and lowercase or uppercase letters -->
			<xs:pattern value="xyz"/> <!-- One character from x, y, z letters -->
			<xs:pattern value="[0-9]"/> <!-- A digit from 0 to 9 -->
			<xs:pattern value="([a-z])*"/> <!-- Any number of lowercase letters -->
			<xs:pattern value="([a-z])+"/> <!-- At least one or more letters -->
			<xs:pattern value="john|jane"/> <!-- john or jane -->
			<xs:pattern value="([a-z])*"/> <!-- Any number of lowercase letters -->
		</xs:restriction>
	</xs:simpleType>
</xs:element>

Try the patterns above one by one. For whitespace handling:

<xs:element name="name">
	<xs:simpleType>
		<xs:restriction base="xs:string">
			<xs:whiteSpace value="preserve"/> <!-- Keeps #x9, #xA, and #xD unchanged -->
			<xs:whiteSpace value="replace"/> <!-- Replaces #x9(tab), #xA, and #xD with #x20(space) -->
			<xs:whiteSpace value="collapse"/> <!-- Collapses whitespace -->
		</xs:restriction>
	</xs:simpleType>
</xs:element>

For character length restrictions:

<xs:element name="name">
	<xs:simpleType>
		<xs:restriction base="xs:string">
			<xs:length value="5"/> <!-- Specifies how many characters there should be -->
			<xs:minLength value="1"/> <!-- Specifies minimum number of characters -->
			<xs:maxLength value="10"/> <!-- Specifies maximum number of characters -->
		</xs:restriction>
	</xs:simpleType>
</xs:element>

Types used in restrictions:

  • enumeration: accepted values
  • fractionDigits: number of digits allowed after the decimal point, such as in 2.4
  • length: exact number of characters
  • maxExclusive: maximum numeric value, excluding the specified value
  • maxInclusive: maximum numeric value, including the specified value
  • maxLength: maximum number of characters
  • minExclusive: minimum numeric value, excluding the specified value
  • minInclusive: minimum numeric value, including the specified value
  • minLength: minimum number of characters
  • pattern: a pattern the value must match
  • totalDigits: total number of digits
  • whiteSpace: whitespace handling behavior