Als je ooit een enterprise XML API hebt geïntegreerd en een cryptische afwijzing ontving met "element 'Quantity' is not valid in this context", heb je al kennisgemaakt met XSD — ook al wist je de naam niet. XML Schema Definition (XSD) is de taal die exact beschrijft hoe geldige XML eruit ziet: welke elementen verplicht zijn, welke datatypes ze bevatten, hoe vaak ze mogen voorkomen en welke waarden zijn toegestaan. Deze gids behandelt hoe je schemas schrijft, er tegenaan valideert en de fouten afhandelt die je onvermijdelijk zult tegenkomen.
XSD is gedefinieerd door de W3C XML Schema-specificatie, voor het eerst gepubliceerd in 2001. De XML Schema Part 2: Datatypes aanbeveling definieert het ingebouwde typesysteem. Het is uitgebreid en enigszins cryptisch om met de hand te schrijven, maar extreem precies — precies wat je nodig hebt bij het uitwisselen van gegevens tussen systemen die geen ambiguïteit tolereren.
Waarom XML überhaupt valideren?
- Vang datafouten vroeg op. Validatie aan de API-grens betekent dat een ontbrekend verplicht veld onmiddellijk mislukt met een duidelijke foutmelding — niet 3 stappen later wanneer je database-insert een constraint-schending gooit.
- Documenteer het contract. Een XSD-schema is uitvoerbare documentatie. In tegenstelling tot een Word-document dat verouderd raakt, is een schema altijd actueel omdat het systeem het afdwingt.
- Interoperabiliteit. In B2B-integraties — facturering, orderbeheer, gezondheidszorg — valideren beide partijen tegen een gedeeld gepubliceerd schema. Als het valideert, kunnen beide kanten het verwerken.
- Beveiliging. Validatie wijst verkeerd gevormde invoer af voordat die de bedrijfslogica bereikt, waardoor het aanvalsoppervlak voor XML-injectieaanvallen wordt verkleind.
Een compleet XSD-schemavoorbeeld
Laten we een schema bouwen voor een productcatalogus. Dit behandelt de meestgebruikte XSD-functies — eenvoudige typen, complexe typen, sequenties, attributen, kardinaliteit en datatype-beperkingen:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- Root element -->
<xs:element name="catalog">
<xs:complexType>
<xs:sequence>
<!-- One or more product elements -->
<xs:element name="product" type="ProductType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="version" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<!-- Product complex type -->
<xs:complexType name="ProductType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="description" type="xs:string" minOccurs="0"/>
<xs:element name="price" type="PriceType"/>
<xs:element name="stock" type="xs:nonNegativeInteger"/>
<xs:element name="categories" type="CategoriesType"/>
</xs:sequence>
<xs:attribute name="id" type="ProductIdType" use="required"/>
<xs:attribute name="status" type="ProductStatusType" use="optional" default="active"/>
</xs:complexType>
<!-- Price with currency attribute -->
<xs:complexType name="PriceType">
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="currency" type="CurrencyCodeType" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<!-- Categories — zero or more category strings -->
<xs:complexType name="CategoriesType">
<xs:sequence>
<xs:element name="category" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!-- Product ID: alphanumeric, starts with P, 4-10 chars -->
<xs:simpleType name="ProductIdType">
<xs:restriction base="xs:string">
<xs:pattern value="P[A-Z0-9]{3,9}"/>
</xs:restriction>
</xs:simpleType>
<!-- Allowed product statuses -->
<xs:simpleType name="ProductStatusType">
<xs:restriction base="xs:string">
<xs:enumeration value="active"/>
<xs:enumeration value="discontinued"/>
<xs:enumeration value="out_of_stock"/>
</xs:restriction>
</xs:simpleType>
<!-- ISO 4217 currency codes — a subset -->
<xs:simpleType name="CurrencyCodeType">
<xs:restriction base="xs:string">
<xs:enumeration value="USD"/>
<xs:enumeration value="EUR"/>
<xs:enumeration value="GBP"/>
<xs:enumeration value="JPY"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>Veel om te verwerken. Laten we de sleutelconcepten doornemen voordat we validatie in actie laten zien.
Sleutel-XSD-concepten uitgelegd
- xs:element. Declareert een element.
minOccursenmaxOccursregelen de kardinaliteit. Standaard voor beide is 1. GebruikmaxOccurs="unbounded"voor onbeperkte herhaling. - xs:complexType. Een element dat child-elementen bevat of attributen heeft. Eenvoudige elementen (alleen tekst) gebruiken
xs:simpleTypeof direct een ingebouwd XSD-type. - xs:sequence. Child-elementen moeten in de gedefinieerde volgorde verschijnen. Het alternatief is
xs:all(willekeurige volgorde, elk maximaal één keer) ofxs:choice(precies één van de vermelde elementen). - xs:attribute use="required". Maakt het attribuut verplicht.
use="optional"(standaard) staat afwezigheid toe. Voegdefault="value"toe voor een standaardwaarde bij afwezigheid. - xs:restriction. Beperkt een basistype. Veelgebruikte facetten:
xs:pattern(regex),xs:enumeration(toegestane waarden),xs:minInclusive/xs:maxInclusive(numerieke grenzen),xs:minLength/xs:maxLength(stringlengte). - xs:simpleContent + xs:extension. De manier om attributen toe te voegen aan een element dat ook tekstinhoud heeft — zoals gebruikt in het bovenstaande
PriceTypewaar<price currency="USD">149.99</price>zowel tekst als een attribuut heeft.
Ingebouwde XSD-datatypes die je echt zult gebruiken
xs:string— willekeurige tekstinhoudxs:integer— gehele getallen (positief, negatief of nul)xs:nonNegativeInteger— gehele getallen ≥ 0 (goed voor hoeveelheden, tellingen)xs:decimal— decimaal met willekeurige precisie (goed voor prijzen)xs:boolean—trueoffalse(accepteert ook1en0)xs:date— ISO 8601-datum:2024-01-15xs:dateTime— ISO 8601 datetime:2024-01-15T09:30:00Zxs:anyURI— een URI/URLxs:base64Binary— Base64-gecodeerde binaire gegevens
XML valideren tegen een XSD in Python (lxml)
Python's standaard xml.etree.ElementTree ondersteunt geen XSD-validatie.
Daarvoor heb je lxml nodig.
De afhankelijkheid is de moeite waard — lxml's validatiemeldingen zijn gedetailleerd en wijzen je naar de exacte
regel die het probleem veroorzaakt:
pip install lxmlfrom lxml import etree
# Load the schema
with open('catalog.xsd', 'rb') as f:
schema_doc = etree.parse(f)
schema = etree.XMLSchema(schema_doc)
# Valid XML
valid_xml = """<?xml version="1.0"?>
<catalog version="1.0">
<product id="P0012" status="active">
<name>Mechanical Keyboard</name>
<price currency="USD">189.00</price>
<stock>42</stock>
<categories>
<category>Electronics</category>
<category>Peripherals</category>
</categories>
</product>
</catalog>"""
xml_doc = etree.fromstring(valid_xml.encode())
if schema.validate(xml_doc):
print("Valid!")
else:
for error in schema.error_log:
print(f"Error at line {error.line}: {error.message}")
# Invalid XML — missing required 'stock', bad product ID format
invalid_xml = """<?xml version="1.0"?>
<catalog version="1.0">
<product id="BADID">
<name>Test Product</name>
<price currency="USD">10.00</price>
<categories/>
</product>
</catalog>"""
invalid_doc = etree.fromstring(invalid_xml.encode())
schema.validate(invalid_doc)
for error in schema.error_log:
print(f"Line {error.line}: {error.message}")
# Line 3: Element 'product', attribute 'id': 'BADID' is not a valid value of the atomic type 'ProductIdType'.
# Line 7: Element 'categories': Missing child element(s). Expected is ( category ). ← if minOccurs > 0Valideren in Java — JAXP
Java heeft ingebouwde XSD-validatie via de JAXP-validatie-API (geen externe bibliotheek nodig). Dit is het patroon dat wordt gebruikt in enterprise Java-applicaties en Spring Boot XML-verwerking:
import javax.xml.XMLConstants;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import org.xml.sax.SAXException;
import java.io.IOException;
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(new File("catalog.xsd"));
Validator validator = schema.newValidator();
try {
validator.validate(new StreamSource(new File("catalog.xml")));
System.out.println("Valid!");
} catch (SAXException e) {
System.out.println("Validation error: " + e.getMessage());
} catch (IOException e) {
System.out.println("IO error: " + e.getMessage());
}XML Schema vs JSON Schema
Als je JSON Schema hebt gebruikt, zal XSD in doel vertrouwd aanvoelen maar heel anders in syntaxis. Een snelle vergelijking:
- Syntaxis. XSD is XML; JSON Schema is JSON. XSD is uitgebreider maar integreert natuurlijk in XML-toolchains.
- Volwassenheid. XSD 1.0 bestaat al sinds 2001 — tientallen jaren aan tooling, validators en bibliotheekondersteuning. JSON Schema evolueert al sinds 2009 en bereikte pas de afgelopen jaren een stabiel concept.
- Typesysteem. XSD heeft een rijker ingebouwd typesysteem:
xs:date,xs:decimal,xs:anyURIzijn ingebouwd. JSON Schema vertrouwt op formaatannotaties voor datums en URI's, die validators al dan niet kunnen afdwingen. - Namespace-ondersteuning. XSD heeft native ondersteuning voor XML-namespaces. JSON Schema heeft geen equivalent concept.
- Wanneer wat te gebruiken. Als je in een XML-ecosysteem werkt, gebruik XSD. Als je in een JSON-ecosysteem werkt, gebruik JSON Schema. Meng ze niet.
Veelvoorkomende validatiefouten en hoe je ze oplost
- "Element X is not expected." Het element verschijnt buiten volgorde in een
xs:sequence, of is helemaal niet gedefinieerd in het schema. Controleer de elementnaam en de positie ten opzichte van de siblingelementen. - "The value Y of attribute Z is not valid." De attribuutwaarde komt niet overeen met het type of de enumeratie. Komt vaak voor bij statusvelden en valutacodes met typfouten.
- "Missing child element(s)." Een verplicht child-element (minOccurs > 0) ontbreekt. Controleer het schema voor welke elementen verplicht zijn onder het bovenliggende element.
- "Not a valid value of the atomic type." Een eenvoudige type-beperking is mislukt — patroon, bereik of enumeratie. Controleer het schema voor de
xs:restrictionop dat type. - "Content model is not determinist." Ambigu schema — de validator kan niet bepalen welke tak van toepassing is. Meestal veroorzaakt door twee opties met dezelfde tagnaam in een
xs:choice.
Gerelateerde tools
Werkt u met XML-schemas? Deze tools kunnen helpen: XML Validator voor snelle welgevormdheidschecks, XML Formatter om dichte XML leesbaar te maken vóór het debuggen, XML Schema Generator om automatisch een XSD te genereren vanuit een voorbeeld-XML-document, en XML to JSON wanneer je liever met JSON Schema werkt.
Samenvatting
XSD is uitgebreid, maar het is het juiste gereedschap voor het definiëren van strikte XML-contracten in enterprise-
en B2B-contexten. De sleutelpatronen om te onthouden: gebruik xs:sequence met
minOccurs/maxOccurs om de structuur te controleren, gebruik xs:restriction
met xs:enumeration en xs:pattern voor waardenbeperking, en gebruik
lxml in Python voor validatie met duidelijke foutmeldingen. Zodra je een werkend schema hebt,
wordt het de enige bron van waarheid waarnaar beide kanten van een integratie kunnen verwijzen —
wat veel heen-en-weer debuggen bespaart.