Guía de XML Schema - Irene-Frias/1DAM GitHub Wiki
XML Schema (XSD - XML Schema Definition) es un lenguaje utilizado para definir la estructura, contenido y restricciones de un documento XML. Su propósito es garantizar que los datos almacenados o intercambiados en XML sigan un formato específico y sean válidos según reglas predefinidas.
A diferencia de DTD (Document Type Definition), XML Schema ofrece una sintaxis más avanzada y expresiva, ya que:
- Está basado en XML, lo que facilita su legibilidad e integración.
- Permite definir tipos de datos (números, fechas, booleanos, etc.).
- Soporta estructuras complejas y reutilización de elementos.
- Es compatible con namespaces, lo que evita conflictos entre esquemas.
La estructura básica de este documento se realiza con un esquema XML Schema
comienza con la declaración del namespace
de XSD
y define los elementos y atributos permitidos en el documento XML
.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- Definición de un elemento simple -->
<xs:element name="persona">
<xs:complexType>
<xs:sequence>
<xs:element name="nombre" type="xs:string"/>
<xs:element name="edad" type="xs:int"/>
<xs:element name="correo" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Hay diferentes componentes claves de un XSD en los que se definen que son los siguientes:
- Elementos se definen cuando un elemento puede ser simple con un solo valor o complejo, es decir con varios subelementos. Como podemos ver en el siguiente ejemplo:
<xs:element name="nombre" type="xs:string"/>
-
Tipos de datos son los definidos el tipo de datos de un elemento o atributo como pueden ser alguno de estos:
-
xs:string
para texto -
xs:int
para número entero -
xs:date
para fecha) -
xs:boolean
para verdadero/falso
-
-
Tipos complejos estos permiten agrupar varios elementos dentro de uno principal. Como se puede ver en el siguiente ejemplo:
<xs:complexType>
<xs:sequence>
<xs:element name="calle" type="xs:string"/>
<xs:element name="ciudad" type="xs:string"/>
</xs:sequence>
</xs:complexType>
-
Secuencias
xs:sequence
son los que indican que los elementos hijos deben aparecer en un orden específico. -
Atributos
xs:attribute
definen propiedades adicionales para los elementos.
<xs:complexType>
<xs:sequence>
<xs:element name="calle" type="xs:string"/>
<xs:element name="ciudad" type="xs:string"/>
</xs:sequence>
</xs:complexType>
-
Restrinciones
xs:restriction
permiten establecer reglas para los valores, como longitud, rango o valores específicos.
<xs:simpleType name="edadLimitada">
<xs:restriction base="xs:int">
<xs:minInclusive value="18"/>
<xs:maxInclusive value="100"/>
</xs:restriction>
</xs:simpleType>
Ejemplo completo con un XML válido con su XSD:
Documento XML persona.xml
<?xml version="1.0" encoding="UTF-8"?>
<persona>
<nombre>Juan Pérez</nombre>
<edad>30</edad>
<correo>[email protected]</correo>
</persona>
Documento esquema XSD persona.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="persona">
<xs:complexType>
<xs:sequence>
<xs:element name="nombre" type="xs:string"/>
<xs:element name="edad" type="xs:int"/>
<xs:element name="correo" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Los tipos simples en XSD definen valores sin estructura interna, es decir, datos que no contienen elementos secundarios o atributos. Son utilizados para restringir valores en elementos y atributos.
Los tipos de datos básico proporcionan varios tipos de datos predefinidos dentro del espacio de nombres xs
que puedan usar directamente en la definición de elementos y atributos.
Tipo de dato | Descripción |
---|---|
xs:string |
Cadenas de texto |
xs:int |
Números enteros |
xs:decimal |
Números decimales |
xs:boolean |
Valores true o flase
|
xs:date |
Fecha en formato YYYY-MM-DD
|
xs:time |
Hora en formato HH:MM:SS
|
xs:dateTime |
Fecha y hora combinadas |
xs:float |
Números en punto flotante |
xs:double |
Doble precisión para decimales |
Ejemplos para definir algunos valores, algunos tipos son los siguientes:
- Decimales, booleanos y fecha.
<xs:element name="precio" type="xs:decimal"/>
<xs:element name="activo" type="xs:boolean"/>
<xs:element name="fechaNacimiento" type="xs:date"/>
- Restringido, permitiendo limitar el rango de valores aceptados.
<xs:simpleType name="edadLimitada">
<xs:restriction base="xs:int">
<xs:minInclusive value="18"/>
<xs:maxInclusive value="100"/>
</xs:restriction>
</xs:simpleType>
- Enumeración, permitiendo uno de los valores especificados en ella.
<xs:simpleType name="tipoSangre">
<xs:restriction base="xs:string">
<xs:enumeration value="A+"/>
<xs:enumeration value="A-"/>
<xs:enumeration value="B+"/>
<xs:enumeration value="B-"/>
<xs:enumeration value="O+"/>
<xs:enumeration value="O-"/>
<xs:enumeration value="AB+"/>
<xs:enumeration value="AB-"/>
</xs:restriction>
</xs:simpleType>
- Lista, permitiendo definir los elementos que contengan los valores separados por espacios.
<xs:simpleType name="coloresPermitidos">
<xs:list itemType="xs:string"/>
</xs:simpleType>
Las facets en XML Schema son restricciones que se aplican a los tipos simples para definir reglas más específicas sobre sus valores. Estas restricciones permiten limitar o modificar cómo se interpretan los datos dentro de un esquema XML.
-
Control de la longitud permiten limitar la cantidad de caracteres que un elemento pueda contener.
-
length
limita la cadena a que sea una longitud exacta -
minLength
limita la cadena a que sea una longitud mínima -
maxLength
limita la cadena a que sea una longitud máxima
-
<xs:simpleType name="codigoPostal">
<xs:restriction base="xs:string">
<xs:length value="5"/>
</xs:restriction>
</xs:simpleType>
- Patrones específicos permiten usar expresiones regulares para definir el formato que debe seguir el valor.
<xs:simpleType name="matricula">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Z]{3}-\d{4}"/>
</xs:restriction>
</xs:simpleType>
-
Manipulación con números permiten establecer valores máximos y mínimos.
-
minInclusive
permite una longitud mínima (incluyendo el valor) -
maxInclusive
permite una longitud máxima (incluyendo el valor) -
minExclusive
permite una longitud mínima (excluyendo el valor) -
maxExclusive
permite una longitud máxima (excluyendo el valor)
-
<xs:simpleType name="edad">
<xs:restriction base="xs:int">
<xs:minInclusive value="18"/>
<xs:maxInclusive value="99"/>
</xs:restriction>
</xs:simpleType>
- Enumeraciones limita los valores posibles a una lista predefinida.
<xs:simpleType name="diaSemana">
<xs:restriction base="xs:string">
<xs:enumeration value="Lunes"/>
<xs:enumeration value="Martes"/>
<xs:enumeration value="Miércoles"/>
<xs:enumeration value="Jueves"/>
<xs:enumeration value="Viernes"/>
</xs:restriction>
</xs:simpleType>
-
Manejo de espacios en blanco definiendo el comportamiento de los espacios en blanco procesados.
-
preserve
mantiene todo igual, es decir no cambia -
replace
reemplaza tabuladores y saltos de línea por espacios -
collapse
elimina múltiples espacios y los reduce a uno solo
-
<xs:simpleType name="textoNormalizado">
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse"/>
</xs:restriction>
</xs:simpleType>
Cuando al especificas un elemento directamente dentro de otro, sin crear ningún tipo con nombre estas definiendo el tipo de especificación local. Esto es útil cuando el tipo solo se usa una vez.
En XML Schema puedes definir el tipo de un elemento de dos formas:
- Localmente: El tipo se define dentro del propio elemento.
- Globalmente: El tipo se define de forma separada y se reutiliza en varios lugares.
<xs:element name="telefono">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="\d{9}"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
Estos tipos locales se usan cuando se necesitan en un único lugar. Otras veces son utilizados para mantener la lógica cerca del dato y cuando no se necesita reutilización en otros elementos.
Son los que permiten representar más de un valor en un solo elemento en el XML. Hay des formas principales en la que puede representarse:
- Listas permite que un elemento contenga varios valores del mismo tipo, separados por espacios.
<!-- De manera global -->
<xs:simpleType name="listaDeEnteros">
<xs:list itemType="xs:int"/>
</xs:simpleType>
<!-- De manera local -->
<xs:element name="codigos">
<xs:simpleType>
<xs:list itemType="xs:string"/>
</xs:simpleType>
</xs:element>
- Uniones permite que un elemento tenga un valor que puede ser de uno entre varios tipos posibles.
<xs:simpleType name="enteroOEspecial">
<xs:union memberTypes="xs:int palabraClave"/>
</xs:simpleType>
<xs:simpleType name="palabraClave">
<xs:restriction base="xs:string">
<xs:enumeration value="N/A"/>
<xs:enumeration value="Desconocido"/>
</xs:restriction>
</xs:simpleType>
La declaración de los tipos simples de manera global fuera de cualquier elemento se puede reutilizar en distintos puntos del esquema. Estos tipos son personalizados definiendo con un nombre y aplicándolos a muchos elementos.
<xs:simpleType name="dniTipo">
<xs:restriction base="xs:string">
<xs:pattern value="\d{8}[A-Z]"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="dni" type="dniTipo"/>
<xs:element name="representanteDni" type="dniTipo"/>
Estos elementos se suelen aplicar en un patrón a varios elementos. Se puede mantener la consistencia y evitar la repetición de dichos elementos. De esta forma puede crearse un esquema menos complejo o extenso.
Tipo de dato | Tipo Global | Tipo Local |
---|---|---|
Definición | Fuera del elemento | Dentro del elemento |
Reutilización | Sí | No |
Legibilidad | Se centraliza en un solo lugar | Más contexto en el lugar usado |
Modularidad | Mejora la organización | No reutilizable fácilmente |
Los valores por defecto se pueden definir como un elemento o atributo, si no se incluye en XML.
Un elemento de tipo complejo es aquel que puede contener otros elementos o atributos. Mientras que los tipos simples son sólo datos (texto, número, fecha), los tipos complejos permiten estructuras. Como se puede ver en el ejemplo:
<!-- Fichero XML -->
<persona>
<nombre>Juan</nombre>
<edad>30</edad>
</persona>
<!-- Fichero XSD -->
<xs:element name="persona">
<xs:complexType>
<xs:sequence>
<xs:element name="nombre" type="xs:string"/>
<xs:element name="edad" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:element>
El contenido de este tipo se puede organizar de tres formas principales dentro de un tipo complejo:
-
xs:sequence
los elementos deben aparecer en el orden exacto en el que se definen. En el orden especificado, como podemos ver en el ejemplo. En el fichero XML se pondría primero la etiquetanombre
y luegoapellido
.
<xs:sequence>
<xs:element name="nombre"/>
<xs:element name="apellido"/>
</xs:sequence>
-
xs:all
todos los elementos pueden aparecer en cualquier orden, pero cada uno como máximo una vez. En este caso no hay orden estipulado, esto quiere decir que podrá ponerse en el orden que se quiera. En el fichero XML se podría poner primero la etiquetaciudad
y luegocalle
o al revés.
<xs:all>
<xs:element name="calle"/>
<xs:element name="ciudad"/>
</xs:all>
-
xs:choice
se elige un solo elemento entre varios elementos posibles. En el fichero XML se podría poner solamente uno como etiquetatelefono
oemail
.
<xs:choice>
<xs:element name="telefono"/>
<xs:element name="email"/>
</xs:choice>
Los grupos de contenido permiten reutilizar combinaciones de elementos. Cada elemento puede tener restricciones:
-
minOccurs
el número mínimo de apariciones. -
maxOccurs
el número máximo de apariciones. En el siguiente ejemplo, podemos ver que puede no aparecer o puede aparecer hasta 3 veces.
<xs:element name="telefono" type="xs:string" minOccurs="0" maxOccurs="3"/>
Cuando declaramos los elementos de tipo complejo de forma global (fuera de los elementos) para poder reutilizarlo.
<xs:complexType name="direccion">
<xs:sequence>
<xs:element name="calle" type="xs:string"/>
<xs:element name="ciudad" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="envio" type="direccion"/>
<xs:element name="facturacion" type="direccion"/>
Además también se permite que un elemento contenga texto y otros subelementos al mismo tiempo.
<!-- Fichero XML -->
<parrafo>Esto es un <negrita>ejemplo</negrita> de contenido mixto.</parrafo>
<!-- Fichero XSD -->
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="negrita" type="xs:string"/>
</xs:sequence>
</xs:complexType>
También se pueden agregar atributos, restricciones,... y tener un tipo totalmente modular.
Los atributos son como propiedades que se agregan a los elementos XML. Se colocan dentro de la etiqueta de apertura del elemento y proporcionan información adicional. En este ejemplo que vemos, el atributo genero
sería el elemento de persona
.
<persona genero="masculino">Juan</persona>
También puedes tener elementos que no contienen texto ni otros elementos, solo atributos:
<entrada activa="true"/>
Si un elemento tiene otros subelementos, aún puedes agregarle atributos. Lo haces dentro de un xs:complexType
con xs:sequence
y luego xs:attribute
.
<xs:complexType>
<xs:sequence>
<xs:element name="nombre" type="xs:string"/>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required"/>
</xs:complexType>
Si el elemento solo contiene texto pero también necesitas un atributo, puedes usar xs:simpleContent
con xs:extension
.
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="formato" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
Puedes limitar lo que se permite como valor de un atributo usando restricciones como pattern
, enumeration,... Como podemos ver en el ejemplo, el atributo
estadosolo puede tener varios valores
"activo"o
"inactivo"`
<xs:attribute name="estado">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="activo"/>
<xs:enumeration value="inactivo"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
Si el atributo no se escribe, se usará un valor predeterminado automáticamente (default
). Si nos basamos en el ejemplo que viene a continuación, si en el XML no se escribe pais, el valor por defecto será "España".
<xs:attribute name="pais" type="xs:string" default="España"/>
Cuando usas fixed
en un atributo, estás diciendo que ese atributo siempre debe tener exactamente ese valor.
No puede cambiarse, ni omitirse (si el elemento lo incluye).
<xs:attribute name="tipo" type="xs:string" fixed="cliente"/>
Si quieres que un atributo sea obligatorio y que siempre esté presente en el XML, debes usar required
<xs:attribute name="id" type="xs:string" use="required"/>
Las estructuras básicas para no confundirte con cierres de etiquetas o elementos:
1. Elemento simple
<xs:element name="nombre" type="xs:string"/>
2. Elemento con restricción
- Con patrón (pattern)
<xs:element name="dni">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="\d{8}[A-Z]"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
- Con rango numérico
<xs:element name="edad">
<xs:simpleType>
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="120"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
- Con enumeración
<xs:element name="nivel">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="básico"/>
<xs:enumeration value="intermedio"/>
<xs:enumeration value="avanzado"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
3. Elemento complejo con subelementos
- Con orden específico (
xs:sequence
)
<xs:element name="direccion">
<xs:complexType>
<xs:sequence>
<xs:element name="calle" type="xs:string"/>
<xs:element name="ciudad" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
- En cualquier orden (
xs:all
)
<xs:element name="datos">
<xs:complexType>
<xs:all>
<xs:element name="nombre" type="xs:string"/>
<xs:element name="apellido" type="xs:string"/>
</xs:all>
</xs:complexType>
</xs:element>
- Uno u otro (
xs:choice
)
<xs:element name="contacto">
<xs:complexType>
<xs:choice>
<xs:element name="telefono" type="xs:string"/>
<xs:element name="email" type="xs:string"/>
</xs:choice>
</xs:complexType>
</xs:element>
4. Elementos con atributos
- Solo atributos
<xs:element name="usuario">
<xs:complexType>
<xs:attribute name="id" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
- Texto + atributos (
simpleContent
)
<xs:element name="comentario">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="autor" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
5. Listas de valores
<xs:element name="hobbies">
<xs:simpleType>
<xs:list itemType="xs:string"/>
</xs:simpleType>
</xs:element>
6. Contenido mixto (texto + subelementos)
<xs:element name="parrafo">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="negrita" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
7. Tipo complejo global reutilizable
<xs:complexType name="personaTipo">
<xs:sequence>
<xs:element name="nombre" type="xs:string"/>
<xs:element name="edad" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:element name="cliente" type="personaTipo"/>
<xs:element name="empleado" type="personaTipo"/>