XML Schema Validation Guide
What Is XML Schema Validation?
Well-formed XML follows syntax rules — tags close properly, attributes are quoted, and one root element wraps everything. Valid XML goes further: it conforms to a schema that defines what elements and attributes are allowed, in what order, with what data types.
The most common schema language is XSD (XML Schema Definition). An XSD file describes the blueprint your XML must follow.
Why Validate Against a Schema?
| Without Schema | With Schema |
|---|---|
| Any element name works | Only declared elements allowed |
| Text appears anywhere | Content restricted to defined types |
| Attributes are unconstrained | Attributes must match declared types |
| Optional/required is ambiguous | minOccurs/maxOccurs enforce cardinality |
| Errors surface at parsing time | Errors caught at validation time — earlier and clearer |
Schema validation catches data problems before they reach your application logic.
Basic XSD Structure
An XSD defines types using <element>, <attribute>, and <simpleType>/<complexType>:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="bookstore">
<xs:complexType>
<xs:sequence>
<xs:element name="book" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="author" type="xs:string"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
<xs:attribute name="id" type="xs:integer" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
This schema requires:
- A root
<bookstore>element - One or more
<book>children (maxOccurs="unbounded") - Each
<book>has<title>,<author>,<price>in that order - Each
<book>has a required integeridattribute <price>must be a decimal number
XSD Data Types
XSD provides built-in types for precise validation:
| Type | Description | Example |
|---|---|---|
xs:string | Text | "Hello" |
xs:integer | Whole number | 42 |
xs:decimal | Fixed-point number | 29.99 |
xs:boolean | True/false | true |
xs:date | Date (YYYY-MM-DD) | 2026-05-28 |
xs:dateTime | Date and time | 2026-05-28T14:30:00 |
xs:email | Email format (via pattern) | user@example.com |
xs:anyURI | URI reference | https://example.com |
xs:token | Whitespace-normalized string | "hello world" |
Restricting Values with simpleType
Custom types add constraints beyond built-in types:
<!-- Enum: only specific values allowed -->
<xs:simpleType name="genreType">
<xs:restriction base="xs:string">
<xs:enumeration value="fiction"/>
<xs:enumeration value="nonfiction"/>
<xs:enumeration value="biography"/>
</xs:restriction>
</xs:simpleType>
<!-- Pattern: regex constraint -->
<xs:simpleType name="isbnType">
<xs:restriction base="xs:string">
<xs:pattern value="\d{3}-\d{1,5}-\d{1,7}-\d{1}"/>
</xs:restriction>
</xs:simpleType>
<!-- Range: numeric bounds -->
<xs:simpleType name="priceType">
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0.01"/>
<xs:maxExclusive value="999.99"/>
</xs:restriction>
</xs:simpleType>
Cardinality Control
| Attribute | Meaning | Default |
|---|---|---|
minOccurs | Minimum occurrences | 1 |
maxOccurs | Maximum occurrences | 1 |
maxOccurs="unbounded" | No upper limit | — |
<!-- Required element, exactly one -->
<xs:element name="title" type="xs:string"/>
<!-- Optional element, zero or one -->
<xs:element name="subtitle" type="xs:string" minOccurs="0"/>
<!-- One to five authors -->
<xs:element name="author" type="xs:string" maxOccurs="5"/>
<!-- Unlimited reviews -->
<xs:element name="review" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
Sequence vs Choice vs All
| Compositor | Behavior |
|---|---|
<xs:sequence> | Elements must appear in order |
<xs:choice> | Exactly one of the listed elements |
<xs:all> | Elements appear in any order, each at most once |
<!-- Either a book or a magazine, not both -->
<xs:choice>
<xs:element name="book" type="bookType"/>
<xs:element name="magazine" type="magazineType"/>
</xs:choice>
Validating XML Against XSD
Command Line
# Using xmllint
xmllint --schema books.xsd books.xml --noout
# Using Java
java -jar jing.jar books.xsd books.xml
JavaScript (Browser)
const parser = new DOMParser();
const doc = parser.parseFromString(xmlString, 'application/xml');
// Browser validators check well-formedness only —
// Full XSD validation requires a server-side tool
Python
from lxml import etree
schema_root = etree.parse('books.xsd')
schema = etree.XMLSchema(schema_root)
doc = etree.parse('books.xml')
is_valid = schema.validate(doc)
# True or False
if not is_valid:
for error in schema.error_log:
print(f"Line {error.line}: {error.message}")
Common Validation Errors
| Error | Cause | Fix |
|---|---|---|
| "Element not expected" | Undeclared element | Add element to schema |
| "Attribute not allowed" | Undeclared attribute | Add attribute to complexType |
| "Text not allowed" | Text in element-only content | Wrap text in a child element |
| "Value not valid" | Wrong data type | Match the declared type |
| "Missing required attribute" | use="required" not satisfied | Add the attribute to XML |
Key Takeaways
- Schema validation catches structural and type errors that well-formedness checks miss
- XSD defines allowed elements, attributes, order, cardinality, and data types
simpleTypewith restrictions enforces enums, patterns, and numeric rangesminOccursandmaxOccurscontrol element frequency- Use command-line tools or language libraries to validate XML against XSD before processing
- Always validate XML from external sources — never trust structure
Try It Yourself
Format and validate your XML documents with our XML Formatter. Paste messy XML, format it for readability, and check well-formedness instantly.