XML Tutorial · Validation · Lesson 10 of 28

XML Schema: Advanced Types

Restrictions and facets, enumerations and patterns, named and derived types, keys and references, and target namespaces.

Create a free account to save this page, take notes and track your progress. Sign in

Restricting simple types with facets

<xs:simpleType name="Sku">
  <xs:restriction base="xs:string">
    <xs:pattern value="[A-Z]{3}-[0-9]{2}"/>       <!-- regular expression -->
  </xs:restriction>
</xs:simpleType>

<xs:simpleType name="Currency">
  <xs:restriction base="xs:string">
    <xs:enumeration value="EUR"/>
    <xs:enumeration value="GBP"/>
    <xs:enumeration value="USD"/>
  </xs:restriction>
</xs:simpleType>

<xs:simpleType name="Price">
  <xs:restriction base="xs:decimal">
    <xs:minInclusive value="0"/>
    <xs:fractionDigits value="2"/>
  </xs:restriction>
</xs:simpleType>

Other facets: minLength/maxLength, length, maxInclusive, minExclusive, totalDigits, whiteSpace.

Named types, extension and keys

  • Define a xs:complexType name="Address" once and reuse it for billing and delivery addresses.
  • Extension derives a type that adds elements or attributes; restriction narrows one.
  • xs:key / xs:keyref / xs:unique enforce identity constraints with XPath, like primary and foreign keys.
  • targetNamespace puts the schema's elements in a namespace; with elementFormDefault="qualified" local elements are namespaced too (almost always what you want).
Patterns, enumerations and uniquenessTry it yourself
from lxml import etree

schema = etree.XMLSchema(etree.fromstring(b"""
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="urn:example:shop" xmlns="urn:example:shop" elementFormDefault="qualified">
  <xs:simpleType name="Sku">
    <xs:restriction base="xs:string"><xs:pattern value="[A-Z]{3}-[0-9]{2}"/></xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="Currency">
    <xs:restriction base="xs:string">
      <xs:enumeration value="EUR"/><xs:enumeration value="GBP"/><xs:enumeration value="USD"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:element name="catalog">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="product" maxOccurs="unbounded">
          <xs:complexType>
            <xs:attribute name="sku" type="Sku" use="required"/>
            <xs:attribute name="currency" type="Currency" use="required"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
    <xs:unique name="uniqueSku">
      <xs:selector xpath="s:product" xmlns:s="urn:example:shop"/>
      <xs:field xpath="@sku"/>
    </xs:unique>
  </xs:element>
</xs:schema>"""))

tests = {
    "ok": '<product sku="TEA-01" currency="EUR"/><product sku="MUG-07" currency="GBP"/>',
    "bad pattern": '<product sku="tea-1" currency="EUR"/>',
    "bad enum": '<product sku="TEA-01" currency="BTC"/>',
    "duplicate sku": '<product sku="TEA-01" currency="EUR"/><product sku="TEA-01" currency="USD"/>',
}
for name, body in tests.items():
    doc = etree.fromstring(f'<catalog xmlns="urn:example:shop">{body}</catalog>'.encode())
    ok = schema.validate(doc)
    print(f"{name}: {'valid' if ok else 'invalid - ' + schema.error_log[0].message}")

Output

ok: valid
bad pattern: invalid - Element '{urn:example:shop}product', attribute 'sku': [facet 'pattern'] The value 'tea-1' is not accepted by the pattern '[A-Z]{3}-[0-9]{2}'.
bad enum: invalid - Element '{urn:example:shop}product', attribute 'currency': [facet 'enumeration'] The value 'BTC' is not an element of the set {'EUR', 'GBP', 'USD'}.
duplicate sku: invalid - Element '{urn:example:shop}product': Duplicate key-sequence ['TEA-01'] in unique identity-constraint '{urn:example:shop}uniqueSku'.

XSD 1.0 vs 1.1

XSD 1.1 (2012) adds assertions (xs:assert test="@end ge @start"), conditional type assignment and xs:all with repeats. libxml2 (lxml, PHP) and the JDK's built-in validator support 1.0 only; for 1.1 use Saxon-EE or Xerces-J's 1.1 build, or express cross-field rules in Schematron.

Test yourself

Which XSD feature works like a database primary key across elements?

  1. xs:key (or xs:unique)
  2. xs:pattern
  3. xs:sequence
  4. xs:any
Show answer

Answer: xs:key (or xs:unique)

Identity constraints select elements with XPath and require their field values to be unique.

Was this page helpful?