# Feature: Schema
Schema permite validar XML con contratos propios del motor. No es XSD completo.
Su objetivo es cubrir validaciones estructurales comunes de forma simple,
tipada y extensible.
## Que aprenderas aqui
[] Declarar rutas requeridas.
[] Validar cardinalidad.
[] Validar tipos simples.
[] Validar valores permitidos.
[] Crear reglas custom.
[] Leer el reporte de validacion.
## Archivo
[] `src/schema/mod.rs`
## Primer contrato
```rust
use xdoc::parser::parse_str;
use xdoc::schema::XmlContract;
let document = parse_str(
"<Order><ID>O-1</ID><Item>A</Item><Item>B</Item></Order>",
)?;
let report = XmlContract::new("order")
.required("/Order/ID")?
.cardinality("/Order/Item", 1, Some(100))?
.validate(&document)?;
assert!(report.is_valid());
```
## Rutas requeridas
```rust
let contract = XmlContract::new("order")
.required("/Order/ID")?
.required("/Order/Customer")?;
```
Si una ruta requerida no produce resultados, el reporte contiene un error.
## Cardinalidad
```rust
let contract = XmlContract::new("order")
.cardinality("/Order/Item", 1, Some(100))?;
```
Esto significa:
[] Minimo 1 `Item`.
[] Maximo 100 `Item`.
Para maximo abierto:
```rust
let contract = XmlContract::new("order")
.cardinality("/Order/Item", 1, None)?;
```
## Tipos simples
```rust
use xdoc::schema::{ValueType, XmlContract};
let contract = XmlContract::new("order")
.text_type("/Order/Total/text()", ValueType::Decimal)?
.text_type("/Order/Approved/text()", ValueType::Boolean)?;
```
Tipos disponibles:
[] `String`
[] `Integer`
[] `Decimal`
[] `Boolean`
## Enumeraciones
```rust
let contract = XmlContract::new("order")
.enum_value("/Order/Status/text()", ["draft", "sent", "accepted"])?;
```
Si el valor no esta en la lista, el reporte marca error.
## Namespaces
Schema usa query por debajo, asi que los namespaces se configuran como aliases.
```rust
let contract = XmlContract::new("document")
.with_namespace("doc", "urn:example:document")?
.required("/doc:Document/doc:ID")?;
```
## Reglas custom
Usa reglas custom cuando una validacion no cabe en required/cardinality/type.
```rust
use xdoc::schema::{ValidationIssue, XmlContract};
let contract = XmlContract::new("order")
.rule(|document| {
let mut issues = Vec::new();
if document.root().is_none() {
issues.push(ValidationIssue::error(
"/",
"document must have a root element",
));
}
Ok(issues)
});
```
## Leer el reporte
```rust
let report = contract.validate(&document)?;
if !report.is_valid() {
for issue in report.errors() {
eprintln!("{}: {}", issue.path(), issue.message());
}
}
```
El reporte separa errores y warnings. Un contrato es valido si no hay issues con
severidad `Error`.
## Cuando usar schema
Usa schema si:
[] Quieres validar XML sin XSD completo.
[] Quieres checks rapidos antes de firmar o transformar.
[] Quieres errores legibles para usuarios.
[] Quieres reglas custom en Rust.
No lo uses si necesitas:
[] XSD completo.
[] Generacion de tipos Rust desde XSD.
[] Validacion normativa de un dominio.
## Errores comunes
[] Esperar que `schema` valide XSD completo.
[] Olvidar aliases de namespace.
[] Usar rutas query no soportadas por el subset.
[] Mezclar reglas de dominio dentro del motor.
## API principal
[] `XmlContract`
[] `ValueType`
[] `ValidationReport`
[] `ValidationIssue`
[] `ValidationSeverity`
[] `ValidationError`
[] `XsdContractAdapter`
## Siguiente lectura
[] [query.md](query.md) para entender las rutas.
[] [transform.md](transform.md) para convertir XML validado.
[] [cli.md](cli.md) para validar desde terminal con contratos simples.
[Volver al indice](features.md).