Se você já integrou com uma API XML corporativa e recebeu uma rejeição críptica com "element 'Quantity' is not valid in this context", você já encontrou o XSD — mesmo sem saber o nome. XML Schema Definition (XSD) é a linguagem que define exatamente como um XML válido deve parecer: quais elementos são obrigatórios, quais tipos de dados eles contêm, quantas vezes podem aparecer e quais valores são permitidos. Este guia cobre como escrever schemas, validar contra eles e lidar com os erros que você inevitavelmente encontrará.
O XSD é definido pela especificação W3C XML Schema, publicada pela primeira vez em 2001. A recomendação XML Schema Part 2: Datatypes define o sistema de tipos embutido. É verboso e um pouco arcano de escrever à mão, mas é extremamente preciso — exatamente o que você precisa ao trocar dados entre sistemas que não podem tolerar ambiguidade.
Por que validar XML?
- Detecte erros de dados cedo. A validação na fronteira da API significa que um campo obrigatório ausente falha imediatamente com um erro claro — não 3 etapas depois, quando a inserção no banco de dados lança uma violação de restrição.
- Documente o contrato. Um schema XSD é documentação executável. Ao contrário de um documento Word que fica desatualizado, um schema é sempre preciso porque o sistema o impõe.
- Interoperabilidade. Em integrações B2B — faturamento, gestão de pedidos, saúde — ambas as partes validam contra um schema publicado compartilhado. Se for válido, ambos os lados podem processá-lo.
- Segurança. A validação rejeita entradas malformadas antes que cheguem à lógica de negócios, reduzindo a superfície de ataque para ataques de injeção XML.
Um Exemplo Completo de Schema XSD
Vamos construir um schema para um catálogo de produtos. Isso cobre os recursos XSD mais usados — tipos simples, tipos complexos, sequências, atributos, cardinalidade e restrições de tipo de dados:
<?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>Muita coisa para absorver. Vamos percorrer os conceitos-chave antes de mostrar a validação em ação.
Conceitos-Chave do XSD Explicados
- xs:element. Declara um elemento.
minOccursemaxOccurscontrolam a cardinalidade. O padrão para ambos é 1. UsemaxOccurs="unbounded"para repetição ilimitada. - xs:complexType. Um elemento que contém elementos filhos ou tem atributos. Elementos simples (somente texto) usam
xs:simpleTypeou um tipo embutido XSD diretamente. - xs:sequence. Os elementos filhos devem aparecer na ordem definida. A alternativa é
xs:all(qualquer ordem, cada um no máximo uma vez) ouxs:choice(exatamente um dos elementos listados). - xs:attribute use="required". Torna o atributo obrigatório.
use="optional"(padrão) permite que esteja ausente. Adicionedefault="value"para um padrão quando ausente. - xs:restriction. Restringe um tipo base. Facetas comuns:
xs:pattern(regex),xs:enumeration(valores permitidos),xs:minInclusive/xs:maxInclusive(limites numéricos),xs:minLength/xs:maxLength(comprimento de string). - xs:simpleContent + xs:extension. A forma de adicionar atributos a um elemento que também tem conteúdo de texto — como usado no
PriceTypeacima, onde<price currency="USD">149.99</price>tem tanto texto quanto um atributo.
Tipos de Dados XSD Embutidos que Você Realmente Vai Usar
xs:string— qualquer conteúdo de textoxs:integer— números inteiros (positivos, negativos ou zero)xs:nonNegativeInteger— inteiros ≥ 0 (bom para quantidades, contagens)xs:decimal— decimal de precisão arbitrária (bom para preços)xs:boolean—trueoufalse(também aceita1e0)xs:date— data ISO 8601:2024-01-15xs:dateTime— datetime ISO 8601:2024-01-15T09:30:00Zxs:anyURI— uma URI/URLxs:base64Binary— dados binários codificados em Base64
Validando XML Contra um XSD em Python (lxml)
O xml.etree.ElementTree padrão do Python não suporta validação XSD.
Você precisa do lxml para isso.
Vale a dependência — as mensagens de validação do lxml são detalhadas e apontam para a linha exata
que está causando o problema:
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 > 0Validando em Java — JAXP
Java tem validação XSD embutida via API de validação JAXP (sem necessidade de biblioteca de terceiros). Este é o padrão usado em aplicações Java corporativas e processamento XML com Spring Boot:
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
Se você já usou JSON Schema, o XSD terá um propósito familiar, mas sintaxe muito diferente. Uma comparação rápida:
- Sintaxe. XSD é XML; JSON Schema é JSON. O XSD é mais verboso, mas se integra naturalmente em cadeias de ferramentas XML.
- Maturidade. XSD 1.0 existe desde 2001 — décadas de ferramentas, validadores e suporte de bibliotecas. JSON Schema vem evoluindo desde 2009 e só alcançou um rascunho estável nos últimos anos.
- Sistema de tipos. O XSD tem um sistema de tipos embutido mais rico:
xs:date,xs:decimal,xs:anyURIsão embutidos. JSON Schema depende de anotações de formato para datas e URIs, que os validadores podem ou não impor. - Suporte a namespaces. O XSD tem suporte nativo a namespaces XML. JSON Schema não tem conceito equivalente.
- Quando usar qual. Se você está trabalhando em um ecossistema XML, use XSD. Se está em um ecossistema JSON, use JSON Schema. Não misture os dois.
Erros de Validação Comuns e Como Corrigi-los
- "Element X is not expected." O elemento aparece fora de ordem em um
xs:sequence, ou não está definido no schema. Verifique o nome do elemento e sua posição em relação aos irmãos. - "The value Y of attribute Z is not valid." O valor do atributo não corresponde ao seu tipo ou enumeração. Comum em campos de status e códigos de moeda com erros de digitação.
- "Missing child element(s)." Um elemento filho obrigatório (minOccurs > 0) está ausente. Verifique no schema quais elementos são obrigatórios sob o pai.
- "Not a valid value of the atomic type." Uma restrição de tipo simples falhou — padrão, intervalo ou enumeração. Verifique o schema para a
xs:restrictionnesse tipo. - "Content model is not determinist." Schema ambíguo — o validador não consegue determinar qual ramo se aplica. Geralmente causado por duas opções com o mesmo nome de tag em um
xs:choice.
Ferramentas Relacionadas
Trabalhando com schemas XML? Essas ferramentas vão ajudar: Validador XML para verificações rápidas de boa formação, Formatador XML para tornar XML denso legível antes de depurar, Gerador de Schema XML para gerar automaticamente um XSD a partir de um documento XML de exemplo, e XML para JSON quando preferir trabalhar com JSON Schema.
Conclusão
O XSD é verboso, mas é a ferramenta certa para definir contratos XML rígidos em contextos
corporativos e B2B. Os padrões-chave para lembrar: use xs:sequence com
minOccurs/maxOccurs para controlar a estrutura, use xs:restriction
com xs:enumeration e xs:pattern para restrições de valor, e use
lxml em Python para validação com mensagens de erro claras. Uma vez que você tenha um schema
funcionando, ele se torna a única fonte da verdade que ambos os lados de uma integração podem referenciar —
o que economiza muito tempo de depuração de ida e volta.