Definición de esquemas y
vocabularios en XML
XML
ha sido propuesto como estándar en el intercambio de información,
independientemente de la plataforma en que se genere o se utilice. Esta
premisa, en principio, es válida siempre y cuando los documentos XML no cambien
durante los intercambios. Si en los intercambios de permite la modificación,
adición o supresión de elementos de información, se ha de tener especial
cuidado de no modificar la estructura del documento. No siempre es posible y
puede llegar el caso en que el mismo documento pueda leerse en una aplicación y
en otra no.
No
solo es imprescindible que el documento esté bien formado (con las etiquetas de
apertura y cierre bien ubicadas, que la codificación sea correcta, que los elementos
cumplan la sintaxis de XML, etc), sino que ambos actores (emisor y receptor) se
ciñan a un mismo formato de fichero definido previamente. Para evitar estos
casos, se ha de definir una estructura fija del documento que conozcan las
partes que intercambian la información.
A
continuación, se mostrarán dos maneras de especificar formatos de comunicación
en XML, las DTD y los XML Schema
DTD
DTD
o Document Type Definition es la definición de cómo se construye un documento
XML para que se ajuste a las necesidades previamente analizadas. Es decir,
establece qué elementos son aceptados y en qué posiciones deben estar dentro de
un documento XML
Cuando
se define una DTD y se referencia dentro de un documento XML, se establece una
relación de:
-
Qué
léxico es el que se espera
-
Qué
reglas sintácticas debe cumplir nuestro lenguaje
El
significado semántico se proporciona en el uso del DTD y del docuemnto XML al
generar las aplicaciones que lo utilizan.
Por
tanto, antes de crear un documento XML se deberá analizar qué elementos y
etiquetas se van a necesitar para la aplicación que se quiere crear. Para esto
sirve una DTD
¿Por
qué resulta importante la creación de DTD? Principalmente, cuando se analiza un
almacenamiento de información en XML es porque esa información es importante
compartirla. Pero aunque la compartición de la información pueda resultar
interesante, la información debe estar sujeta a una serie de reglas para que
todos los que lo utilicen(en consultas, inserciones, modificaciones, borrados,
etc) y debe resultar bien formado y válido para el uso por terceras aplicaciones.
Si en el proceso de acceso y modificación del documento XML se incumple su
estructura, nos encontraremos con un documento no válido y con un futuro
problema. Por tanto, una DTD permitirá asegurar que la información que contiene
es válida y cumple los requisitos de intercambio de información entre personas
con la misma DTD.
La
creación de una DTD resulta muy simple:
- La
DTD se puede ubicar dentro del propio documento XML
- La
DTD se ubica en un fichero externo fuera del documento XML (Con extensión
XML)
Ambas
realizan la misma función pero resulta más cómoda utilizar un fichero externo
para almacenar la DTD y realizar un enlace en el docuemnto XML para que la use.
Además de la comodidad, existe otra ventaja fundamental: no se almacena en cada
documento XML la DTD. Si tuviésemos muchos ficheros XML, basados en la misma
especificación DTD, se tendría que cambiar en todos los ficheros la declaración
de la DTD, cosa que si estuviera enlazado en un fichero externo, se cambiaría
una única vez y todos los documentos XML lo aprovecharían. Además se estaría
almacenando la misma información en todos los documentos, lo que aumentaría el
tamaño del documento XML.
Para
continuar, establezcamos un ejemplo en el que utilizar una DTD. Se quiere
almacenar los mensajes de móviles que se envían a un servidor. Los datos se
guardarán son los siguientes:
-
Número de
teléfono del usuario
-
Fecha de
envío
-
Hora de
envío
-
Contenido
del mensaje
<?xml
version="1.0" encoding="utf-8"?>
<!DOCTYPE
BDsms SYSTEM “BDsms.dtd”>
<BDsms>
<sms>
<telefono>
955 65 55 55 </telefono>
<fecha>1/7/2011</fecha>
<hora>23:55</hora>
<mensaje>Juego1:
Tetris</mensaje>
</sms>
<sms>
<telefono>542
000 000</telefono>
<fecha>
10/11/2011</fecha>
<hora>09:22</hora>
<mensaje>Juego2:
Comecocos</mensaje>
</sms>
</BDsms>
LA
DTD que permite establecer el formato de intercambio de estos mensajes SMS, en
el documento XML, podría ser el siguiente (fichero “BDsms.dtd”)
Notad
que el fichero BDsms está referenciado en el documento XML. Si se quisiera incluir
todo en el mismo documento XML, entonces quedaría:
<?xml
version="1.0" encoding="utf-8"?>
<!DOCTYPE BDsms [
<!ELEMENT
BDsms (sms*)>
<!ELEMENT sms (telefono, fecha, hora,
mensaje)>
<!ELEMENT telefono (#PCDATA)>
<!ELEMENT fecha (#PCDATA)>
<!ELEMENT hora (#PCDATA)>
<!ELEMENT mensaje (#PCDATA)>
]>
<BDsms>
<sms>
<telefono>
955 65 55 55 </telefono>
<fecha>1/7/2011</fecha>
<hora>23:55</hora>
<mensaje>Juego1:
Tetris</mensaje>
</sms>
<sms>
<telefono>542
000 000</telefono>
<fecha>
10/11/2011</fecha>
<hora>09:22</hora>
<mensaje>Juego2:
Comecocos</mensaje>
</sms>
</BDsms>
Bloques para construir
una DTD
Viendo
el ejemplo de la base de datos de SMS, se puede observar una serie de elementos
definidos en una DTD:
-
Elemento.
Es el bloque principal con el que se construyen los elementos DTD
-
Atributo:
Forma de añadir más información a un elemento
-
Entidad.
En XML existen algunos caracteres que tienen un significado especial. La
aparición de estos caracteres como datos almacenables hace que se puedan
confundir con entidades propias de un documento XML. Son entidades las
siguientes:
o
=> Espacio en blanco
o
>
=> >
o
<
=> <
o
"
=> “
o
'
=> ‘
o
&
=> &
-
Se pueden
usar dentro del propio documento XML y tras parsear el documento tomarán el
valor indicado a la derecha. También el usuario puede definir entidades propias
para que, después de analizar el documento XML, se sustituyan por el valor
indicado. Es como una especie de definición preestablecida. Un par de ejemplos
son los siguientes:
o
<!ENTITY
pi “3.14.15.92”> => π
o
<!ENTITY textFile SYSTEM “fichero.txt”> =>&textFile
o
<!ENTITY miURL SYSTEM http://www.as.com>
=> miURL
-
PCDATA. Su
significado en inglés es Parsed Character Data. Indica que entre la etiqueta y
cierre de apertura de ese elemento, se almacenarán caracteres como texto y
serán analizados por un parser. Como es lógico, al analizarse mediante el
parser el contenido del texto para encontrar entidades y elementos, si es solo texto
no podrá encontrarse ninguno de los caracteres anteriormente mencionados (pues
podría confundir al parser a la hora de analizar el documento XML)
-
CDATA..
Su significado en inglés Character Data. A efectos es prácticamente igual que
PCData pero el contenido de ese elemento, entre sus etiquetas de apertura y
cierre, no se analizará por el parser de análisis de entidades y elementos XML.
Los
elementos se declaran de una de las dos siguientes maneras:
<!ELEMENT
nombre_del_elemento categoría>
O
<!ELEMENT
nombre_del_elemento (nodos_hijos)>
En
el segundo caso se pueden definir el nombre_del_elemento como el nodo padre del
que cuelgan un conjunto de nodos hijos (separados por comas)
Si
existiera algún elemento que deba estar vacío, existe la palabra reservada EMPTY
que puesta en la zona de “categoría” permite indicar este hecho. Un ejemplo de
uso es la etiqueta <br> de HTML. Esta etiqueta permite establecer un salto
de línea pero debería estar indicado como <br></br>. Si se declara
como EMPTY, entonces se podría simplificar el salto de línea de la siguiente
manera :<br />
<!ELEMENT
saltoLinea EMPTY> => <saltoLinea />
<!ELEMENT
telefono (#PCDATA)>
<!ELEMENT
hora (#CDATA)>
En
el caso concreto de ANY, permite indicar que cualquier combinación de elementos
conocidos serían válidos en ese caso.
<!ELEMENT
hora (#ANY)> => Podría valer teléfono, fecha, mensaje,…
No
se ha comentado nada, hasta el momento, sobre los atributos. La manera de
declararlos en un DTD es mediante la siguiente sintaxis:
<!ATTLIST
nombre_elemento nombre_atributo tipo_atributo valor_por_defecto>
-
Nombre_elemento:
es el elemento al que se le quiere añadir el atributo.
-
Nombre_atributo:
es el nombre del atributo que se quiere añadir.
-
Tipo_atributo:
existen muchos tipos de atributos destacan:
o
CDATA:
es un texto. Podrán tener cualquier carácter
o
ID:
Es un identificador que permite identificar el elemento de manera única en todo
documento XML
o
IDREF:
Es un identificador de otro elemento del propio documento XML
o
IDREFS:
Es una lista de identificadores a otros elementos (tipo1 | tipo2 | tipo3 | …)
el valor es uno de los indicados en esta lista enumerada (definida por el usuario).
o
NMTOKEN:
Es un texto que solo podrá tener letras, dígitos, guión, “-“, punto, “.”, y dos
puntos “:”. Es lo que se llama nombres válidos XML
o
NMTOKENS:
Es una lista de nombres XML válidos. Es como un NMTOKEN pero se incluyen los
espacios en blanco, “ “, tabuladores o retornos del carro.
o
ENTITY:
El tipo de atributo es una entidad que se ha declarado anteriormente
o
ENTITIES:
Es una lista de entidades
Los
atributos podrán ser declarados como obligatorios #REQUIRED, optativos,
#IMPLIED o fijos #FIXED. Este último obliga al usuario que el atributo sea
siempre el mismo, sin que pueda cambiarlo (si se cambia no estaría conforme a
la DTD declarada y devolvería un error)
Como
no se ha declarado ningún atributo en el ejemplo de los SMS, cambiaremos el
elemento hora para añadir la zona o
franja horaria (de manera obligatoria). Se quiere tener un documento XML de
este tipo:
….
<hora zona=”GMT+1”>09:22</hora>
.…
Por
lo que el DTD debe añadir la siguiente línea:
<!ATTLIST
hora zona CDATA “GMT+1” #REQUIRED>
Secuencias de elementos:
Estructura con hijos
Podemos
ver que el elemento sms está compuesto por teléfono, fecha, hora y mensaje.
Esta es una relación padre-hijos. Imaginemos que una vez definida una DTD, nos
damos cuenta que, por cada SMS recibido se pueden almacenar varios mensajes. En
este caso debería cambiar la ocurrencia de la aparición de los elementos justo
cuando los indicamos en el elemento padre. Las ocurrencias que pueden aparecer
se indican con los siguientes operadores:
-
“: Indica
que aparece obligatoriamente una vez. Es el caso inicial en cuanto se declara
un hijo al elemento sms.
-
“+”:
indica que puede haber una o más ocurrencias del elemento indicado
o
<!ELEMENT
sms (teléfono, fecha, hora, mensaje+)>
-
“*”:
Indica que puede haber cero o más ocurrencias del elemento indicado
o
<!ELEMENT
sms (teléfono, fecha, hora, mensaje*)>
-
“?”:
indica que puede haber cero o una ocurrencia del elemento indicado (también
llamado opcionalidad)
o
<!ELEMENT
sms (teléfono, fecha, hora, mensaje?)>
No
solo se pueden cambiar las ocurrencias de los hijos declarados, sino que
podemos indicar la opcionalidad de la aparición de hijos. En este caso
podríamos definir que querremos almacenar o la hora o el mensaje pero no las
dos simultáneamente pero sí obligatoriamente una de las dos, por lo que
quedaría así:
<!ELEMENT
BDsms (sms*)>
<!ELEMENT
sms (telefono, fecha, (hora | mensaje)>
<!ELEMENT
telefono (#PCDATA)>
<!ELEMENT
fecha (#PCDATA)>
<!ELEMENT
hora (#PCDATA)>
<!ELEMENT
mensaje (#PCDATA)>
Ejemplo.
Se
quiere crear una biblioteca de libros en un documento XML. Para ello, se
necesita crear una DTD que almacene los siguientes campos de un libro:
- Código
del libro
- Título
- Editorial
- Edición
- ISBN
- Número
de páginas
- Autor
Como DTD incrustada :
<?xml
version="1.0" encoding="utf-8"?>
<!DOCTYPE biblioteca [
<!ELEMENT biblioteca (libro*)>
<!ELEMENT libro (codigo, titulo, Editorial,
Edicion, ISBN, Numero_de_paginas, Autor)>
<!ELEMENT codigo (#PCDATA)>
<!ELEMENT titulo (#PCDATA)>
<!ELEMENT Editorial (#PCDATA)>
<!ELEMENT Edicion (#PCDATA)>
<!ELEMENT ISBN (#PCDATA)>
<!ELEMENT Edición (#PCDATA)>
<!ELEMENT Numero_de_paginas (#PCDATA)>
<!ELEMENT Autor (#PCDATA)>
]>
<biblioteca>
<libro>
<codigo>
001
</codigo>
<titulo>
El Oscuro PAsajero
</titulo>
<Editorial>
Umbriel
</Editorial>
<Edicion>
La primera
</Edicion>
<ISBN>
84-95618-83-4
</ISBN>
<Numero_de_paginas>
251
</Numero_de_paginas>
<Autor>
Jeff Lindsay
</Autor>
</libro>
</biblioteca>
Si
lo validamos en la dirección http://www.xmlvalidation.com/
Podemos
comprobar que se valida sin problemas:
¿Cómo
hacer la validación para incluir esta misma información de DTD desde un fichero externo?
Antes
que nada debemos separar los dos ficheros que tendremos ahora, biblioteca.xml y
biblioteca.dtd:
Primer fichero biblioteca.xml
<?xml
version="1.0" encoding="utf-8"?>
<!DOCTYPE
biblioteca SYSTEM "biblioteca.dtd">
<biblioteca>
<libro>
<codigo>
001
</codigo>
<titulo>
El Oscuro PAsajero
</titulo>
<Editorial>
Umbriel
</Editorial>
<Edicion>
La primera
</Edicion>
<ISBN>
84-95618-83-4
</ISBN>
<Numero_de_paginas>
251
</Numero_de_paginas>
<Autor>
Jeff Lindsay
</Autor>
</libro>
</biblioteca>
Segundo fichero
biblioteca.dtd
<!ELEMENT
biblioteca (libro*)>
<!ELEMENT libro (codigo, titulo, Editorial,
Edicion, ISBN, Numero_de_paginas, Autor)>
<!ELEMENT codigo (#PCDATA)>
<!ELEMENT titulo (#PCDATA)>
<!ELEMENT Editorial (#PCDATA)>
<!ELEMENT Edicion (#PCDATA)>
<!ELEMENT ISBN (#PCDATA)>
<!ELEMENT Edición (#PCDATA)>
<!ELEMENT Numero_de_paginas (#PCDATA)>
<!ELEMENT Autor (#PCDATA)>
Para
validar ambos elementos, ahora procedemos a la dirección anterior:
Cargamos
en primer lugar el archivo xml. Después hacemos clic en validar
Y
nos aparece lo siguiente:
Aquí
nos está informando de que el archivo tiene una referencia a una dtd y que para
validar ambas, debemos incluir a continuación el contenido del archivo dtd. Lo
hacemos:
Y,
tras hacer clic en “continue validation” (Continuar validación)
Nos
dice lo siguiente:
No
hubo errores encontrados, así que nuestros documentos, tanto DTD como XML están
bien formados y, además, son válidos.
No hay comentarios:
Publicar un comentario