 Tutoriales
Apuntes de XML
Restringir documentos XML
¿Por qué restringir los datos?
DTD's
Un ejemplo de DTD
- Para utilizar una DTD como mecanismo de restricción, se
especifica lo siguiente en el documento XML:
<!DOCTYPE Libro SYSTEM "libro.dtd">
- DTD para el ejemplo del libro:
<!ELEMENT Libro
(Titulo, Catalogo:Seccion, Catalogo:SubSeccion,
Contenido, Compra, Copyright)>
<!ATTLIST Libro
xmlns CDATA #REQUIRED
xmlns:Catalogo CDATA #REQUIRED
>
<!ELEMENT Titulo (#PCDATA)>
<!ELEMENT Catalogo:Seccion (#PCDATA)>
<!ELEMENT Catalogo:SubSeccion (#PCDATA)>
<!ELEMENT Contenido ((Capitulo+)|(Capitulo+, Separacion?)+)>
<!ELEMENT Capitulo (Tema, Seccion+)>
<!ATTLIST Capitulo
materia (XML|Java) "Java"
>
<!ELEMENT Tema (#PCDATA)>
<!ELEMENT Seccion (#PCDATA)>
<!ATTLIST Seccion
apartados CDATA #REQUIRED
dificil (si|no) "no"
>
<!ELEMENT Separacion EMPTY>
<!ELEMENT Compra (#PCDATA)>
<!ELEMENT Copyright (#PCDATA)>
<!ENTITY OReillyCopyright SYSTEM "copyright.txt">
Elementos
- Los elementos permitidos se especifican con
ELEMENT, seguido del nombre y el tipo del elemento.
- Los elementos que se pueden anidar dentro de otros se
especifican entre paréntesis y separados por comas. Importa el
orden.
- El tipo menos restrictivo es ANY, que permite cualquier
contenido para un elemento.
- Para datos de tipo texto, se usa #PCDATA.
- Para elementos vacíos, EMPTY.
- Modificadores de número de ocurrencias:
- ?: Una vez o ninguna
- +: Al menos una vez
- *: Cualquier número de veces o ninguna
- (nada): Exactamente una vez
- Para opciones alternativas: separar con |.
Atributos
- Los atributos permitidos para un elemento se
especifican con ATTLIST y el nombre del elemento seguido
de los nombres de los atributos, con un tipo y modificador
obligatorios.
- El tipo del atributo puede ser CDATA para
cualquier valor, o una enumeración de los valores permitidos.
- Otros posibles tipos son:
- NMTOKEN para restringir el valor a un nombre XML
válido (es decir, que empiece con una letra o guión de
subrayado y contenga sólo letras, números, guiones de subrayado,
guiones y puntos, sin espacios)
- ID, además de las restricciones que impone
NMTOKEN, impone que el valor sea único en todo
el documento.
- El modificador puede ser #REQUIRED para
atributos obligatorios, #IMPLIED para opcionales, o
#FIXED valor_fijo para valores fijos. También puede ser
un valor por defecto.
Declaración DOCTYPE
Entidades
Esquemas XML
Esquemas XML vs DTDs
- Ventajas sobre las DTDs:
- Restricciones más precisas sobre los documentos XML
(tanto en estructura como en tipos de datos).
- Son documentos XML, por lo que la sintaxis es
familiar y las herramientas los pueden manejar sin técnicas
especiales (no como las DTDs).
- Soporte para espacios de nombres.
- Permiten definir elementos globales y locales (las
DTDs sólo globales).
- Desventajas sobre las DTDs:
- Más complejos. Esto causa:
- Dificultades en su comprensión por humanos, sobre todo si
están acostumbrados a las DTDs.
- Herramientas más grandes y lentas.
- Muchas aplicaciones funcionan ya sobre DTDs
existentes (la conversión es posible pero llevará un
tiempo).
- Se trata de una especificación muy reciente, por lo que el
soporte por parte de muchas herramientas aún está en
proceso.
Un primer ejemplo
- Pasemos a esquema XML esta sencilla DTD:
<!ELEMENT Libreria (Libro)+>
<!ELEMENT Libro (Titulo, Autor+, Fecha, ISBN)>
<!ELEMENT Titulo (#PCDATA)>
<!ELEMENT Autor (#PCDATA)>
<!ELEMENT Fecha (#PCDATA)>
<!ELEMENT ISBN (#PCDATA)>
- Un esquema XML equivalente:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.libros.org"
xmlns="http://www.libros.org"
elementFormDefault="qualified">
<xs:element name="Libreria" type="TipoLibreria"/>
<xs:complexType name="TipoLibreria">
<xs:sequence>
<xs:element name="Libro" type="TipoLibro" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="TipoLibro">
<xs:sequence>
<xs:element name="Titulo" type="xs:string"/>
<xs:element name="Autor" type="xs:string" maxOccurs="3"/>
<xs:element name="Fecha" type="xs:string"/>
<xs:element name="ISBN" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Características
- Observar que, a diferencia de la DTD, es XML.
- Observar cómo los elementos más generales referencian a
los más concretos, hasta llegar a los más básicos. No es la única
forma de hacerlo.
- minOccurs y maxOccurs por defecto valen 1.
- Observar cómo definimos los elementos básicos como de
tipo string.
- Los elementos vacíos se definen con un
complexType sin elementos.
Espacios de nombres
- Hay múltiples espacios de nombres involucrados en un
esquema:
- Para los elementos del propio esquema
(xmlns:xs).
- Para los elementos a restringir
(targetNamespace).
- Para los elementos referenciados con el atributo
ref (xmlns), se verá un ejemplo al final.
- El atributo elementFormDefault sirve para exigir que
al usar el esquema desde un documento los elementos se
asocien con el targetNamespace del esquema.
Uso desde un documento
- Este es un pequeño documento XML que utiliza el
esquema:
<?xml version="1.0"?>
<Libreria xmlns="http://www.libros.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.libros.org libreria.xsd">
<Libro>
<Titulo>My Life and Times</Titulo>
<Autor>Paul McCartney</Autor>
<Autor>Phil McCartney</Autor>
<Fecha>July, 1998</Fecha>
<ISBN>94303-12021-43892</ISBN>
</Libro>
...
</Libreria>
Más estructuras
- Otras posibilidades de estructura, además de
sequence:
- choice: Para alternativas.
- all: Para conjuntos de elementos en los que no
importa el orden.
- Las tres estructuras pueden tener maxOccurs (en
all el máximo es 1) y minOccurs
Tipos
Atributos
- Veamos cómo se tratan los atributos de los elementos. Dado el
siguiente fragmento de DTD:
<!ELEMENT Libro (Titulo, Autor+, Fecha, ISBN)>
<!ATTLIST Libro
Categoria (biografia | ensayo | ficcion) #REQUIRED
Disponible (true | false) "false"
Corrector CDATA ""
>
- Resulta el siguiente fragmento de esquema XML:
<xs:complexType name="TipoLibro">
<xs:sequence>
<xs:element name="Titulo" type="xs:string"/>
<xs:element name="Autor" type="xs:string" maxOccurs="3"/>
<xs:element name="Fecha" type="xs:string"/>
<xs:element name="ISBN" type="xs:string"/>
</xs:sequence>
<xs:attribute name="categoria" type="TipoCat" use="required"/>
<xs:attribute name="disponible" type="xs:boolean" default="false"/>
<xs:attribute name="corrector" type="xs:string" default=""/>
</xs:complexType>
<xs:simpleType name="TipoCat">
<xs:restriction base="xs:string">
<xs:enumeration value="biografia"/>
<xs:enumeration value="ensayo"/>
<xs:enumeration value="ficcion"/>
</xs:restriction>
</xs:simpleType>
- Si un elemento tiene contenido simple y atributos (por
ejemplo: <elem atr=h4>678</elem>), se
restringe así:
<xs:element name="elem">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:integer">
<xs:attribute name="atr" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
Importar esquemas
Un ejemplo completo
- Para terminar, un ejemplo completo de un esquema XML:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.miempresa.org/pedidos"
xmlns="http://www.miempresa.org/pedidos"
elementFormDefault="qualified">
<xs:element name="Pedido" type="TipoPedido"/>
<xs:complexType name="TipoPedido">
<xs:sequence>
<xs:element name="Destino" type="TipoDireccion"/>
<xs:element name="Ordenante" type="TipoDireccion"/>
<xs:element name="Observaciones" type="xs:string" minOccurs="0"/>
<xs:element name="Contenido" type="TipoContenido"/>
</xs:sequence>
<xs:attribute name="fecha" type="xs:date" use="required"/>
</xs:complexType>
<xs:complexType name="TipoDireccion">
<xs:sequence>
<xs:element name="Nombre" type="xs:string"/>
<xs:element name="Direccion" type="xs:string"/>
<xs:element name="Ciudad" type="xs:string"/>
<xs:element name="CodPostal" type="TipoCodPostal"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="TipoCodPostal">
<xs:restriction base="xs:positiveInteger">
<xs:minInclusive value="1000"/>
<xs:maxInclusive value="60000"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="TipoContenido">
<xs:sequence>
<xs:element name="Producto" type="TipoProducto" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="TipoProducto">
<xs:sequence>
<xs:element name="Nombre" type="xs:string"/>
<xs:element name="Cantidad" type="TipoCantidad"/>
<xs:element name="Precio" type="xs:decimal"/>
<xs:element name="Observaciones" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="codigo" type="TipoCodigo" use="required"/>
</xs:complexType>
<xs:simpleType name="TipoCantidad">
<xs:restriction base="xs:positiveInteger">
<xs:maxExclusive value="100"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TipoCodigo">
<xs:restriction base="xs:string">
<xs:pattern value="\d{3}-[A-Z]{2}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
- Y un documento que lo utiliza:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Pedido xmlns="http://www.miempresa.org/pedidos"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.miempresa.org/pedidos pedido.xsd"
fecha="1999-10-20">
<Destino>
<Nombre>Alicia Abad</Nombre>
<Direccion>Plaza de la Duquesa 12</Direccion>
<Ciudad>Albacete</Ciudad>
<CodPostal>05020</CodPostal>
</Destino>
<Ordenante>
<Nombre>Roberto Movilla</Nombre>
<Direccion>General Ricardos 56</Direccion>
<Ciudad>Madrid</Ciudad>
<CodPostal>28055</CodPostal>
</Ordenante>
<Observaciones>Es urgente, mi cesped está muy alto</Observaciones>
<Contenido>
<Producto codigo="872-AA">
<Nombre>Cortadora de cesped</Nombre>
<Cantidad>1</Cantidad>
<Precio>148.95</Precio>
<Observaciones>Confirmar que es eléctrica</Observaciones>
</Producto>
<Producto codigo="926-FH">
<Nombre>Taladradora</Nombre>
<Cantidad>3</Cantidad>
<Precio>10.98</Precio>
</Producto>
</Contenido>
</Pedido>
Otras formas de construir esquemas XML
- Anidando los elementos:
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.libros.org"
xmlns="http://www.libros.org">
<xsd:element name="Libreria">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Libro" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Titulo" type="xsd:string"/>
<xsd:element name="Autor" type="xsd:string"/>
<xsd:element name="Fecha" type="xsd:string"/>
<xsd:element name="ISBN" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
- Referenciando a los elementos:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.libros.org"
xmlns="http://www.libros.org">
<xs:element name="Libreria">
<xs:complexType>
<xs:sequence>
<xs:element ref="Libro" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Libro">
<xs:complexType>
<xs:sequence>
<xs:element ref="Titulo" minOccurs="1" maxOccurs="1"/>
<xs:element ref="Autor" minOccurs="1" maxOccurs="unbounded"/>
<xs:element ref="Fecha" minOccurs="1" maxOccurs="1"/>
<xs:element ref="ISBN" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Titulo" type="xs:string"/>
<xs:element name="Autor" type="xs:string"/>
<xs:element name="Fecha" type="xs:string"/>
<xs:element name="ISBN" type="xs:string"/>
</xs:schema>
- En ambos casos se utilizan tipos complejos anónimos
(sin nombre).
- Se puede hacer lo mismo con los tipos simples.
|
|
|