Cerrar

Enviar mensaje

twitter FaceBook You Tube Git Hub Enviar email

Manual de XML

[3]
Validación de documentos XML

Publicidad

[3.1] documentos XML bien formados y validación

[3.1.1]introducción

En el tema anterior se dispusieron las bases del funcionamiento de XML. En ese misma tema distinguimos lo que se considera un documento XML bien formado. Los documentos bien formados, aseguran que las reglas de XML se cumplen y que no hay ninguna incoherencia al usar el lenguaje.

Sin embargo, aun los documentos XML bien formados darían problemas a la hora de elaborar documentos XML propios, ya que os documentos no tienen porque mantener homogeneidad y sin embargo estar bien formados. Sin embargo esa homogeneidad es vital para poder manipular documentos XML.

Por ejemplo supongamos que disponemos de un servicio de Internet que permite informar sobre el tiempo que hace en nuestra zona. Supongamos también que entregamos esa información en XML. Para ello podríamos elaborar un XML con el tiempo de cada día y desde Internet cuando se solicite un día concreto, entregar el XML correspondiente.

Para que ese servicio sea útil, la estructura del XML de cada día debe ser igual, de otro modo los servicios que requieren nuestra información no funcionarían adecuadamente. Así si en nuestro XML indicamos la fecha y luego la temperatura, habrá que mantener ese orden siempre.

De ahí sale la idea de validación. Un documento XML es válido si ha pasado las reglas definidas en otro documento llamado documento de validación. De modo que, un documento XMl que sea válido deberá indicar qué plantilla de reglas utiliza y deberá cumplirlas a rajatabla.

Así explicado parece que la validación supone un problema, pero en realidad es una ventaja; con la validación tenemos la seguridad de que los documentos cumplen unas reglas más concretas y de esa forma es fácil establecer un protocolo en las empresas para sus documentos. En definitiva la validación permite establecer lenguajes propios de marcado para nuestros documentos.

[3.1.2]principales lenguajes de validación

Las técnicas más populares para definir validaciones son:

Es la técnica más veterana y, en realidad procede de SGML el lenguaje base de XML. Es indudablemente la más utilizada, pero también la menos coherente con las reglas XML. Su éxito se debe a que ya era una forma de validación reconocida antes de la aparición de XML, por lo que muchísimo productos software la reconocen desde hace mucho. La enorme compatibilidad que posee, ha determinado su éxito.

[3.2.2]cómo indicar que un XML cumple las reglas de un DTD

Si queremos que un documento XML cumpla las reglas de validación establecidas mediante el lenguaje DTD, tenemos varias opciones.

17en el propio documento

Se puede definir la estructura que debe cumplir un documento XML mediante código DTD insertado en el propio documento. La desventaja evidente, es que estremos definiendo reglas que solo se aplican a un documento.

Realmente no define tipos de documentos XML. No es una plantilla, en definitiva, de definición de documentos. Por ello es la forma menos habitual de utilizar DTD.

Su única (pero muy discutible) ventaja es que la validación está dentro del propio documento, por lo que siempre viajan juntas la validación y el contenido del mismo.

Un documento XML que defina internamente su DTD, simplemente escribe instrucciones DTD dentro del propio documento dentro de una etiqueta DOCTYPE. La sintaxis es:

<!DOCTYPE raíz [....códigoDTD...]>

Dentro de los símbolos [ y ] se especifican las instrucciones DTD. Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE persona [
	<!ELEMENT persona (nombre)>
	<!ELEMENT nombre (#PCDATA)>	
]>
<persona>
	<nombre>Antonio</nombre>
</persona>

Ese documento es válido ya que cumple las reglas establecidas directamente en la etiqueta DOCTYPE.

18en un documento externo privado

En este caso la validación se crea en un documento DTD externo e independiente. De modo que cuando un documento queremos que cumpla las reglas de ese, se debe indicar la ruta (sea relativa o absoluta) al mismo.

La sintaxis de la etiqueta DOCTYPE que permite asignar un DTD privado a un documento XML es:

<!DOCTYPE raíz SYSTEM “ruta_URL_al_DTD”>

Salvo que se desee crear un único documento con una validación DTD, lo lógico es utilizar la forma de DTD externa ya que de esa forma se pueden validar varios documentos a la vez. La ruta puede ser absoluta y entonces se indica su URL:

<!DOCTYPE raíz SYSTEM “http://www.empresa.com/docs.dtd”>

Pero puede ser relativa:

<!DOCTYPE raíz SYSTEM “docs.dtd”>

Entonces se busca al archivo DTD desde el directorio donde se encuentra el archivo XML que queremos validar (en el ejemplo, el archivo docs.dtd debe encontrarse en el mismo directorio que el archivo XML).

En ambos casos se puede añadir código DTD para en ese documento concreto añadir instrucciones de validación.

Ejemplo:

<!DOCTYPE raíz SYSTEMhttp://www.empresa.com/docs.dtd[
<!ELEMENT nombre (#PCDATA)>
] >

19DTD externo de tipo PUBLIC

Se entiende que la palabra SYSTEM se utiliza cuando el documento DTD es privado. Si se trata de un documento de uso público, entonces se usa PUBLIC. La sintaxis, en este caso, es:

<!DOCTYPE raíz PUBLIC “nombreDTD” “DTD_URL”>

La raíz sigue siendo el nombre del elemento raíz. El nombreDTD es el nombre público que se le da al DTD en cuestión. Si disponemos de un repositorio de DTDs públicos (como ocurre en entornos de trabajo como Oxygene por ejemplo) le cargaría sin ir a Internet. Si el nombreDTD no es reconocido se usa la dirección URL para descargarlo y utilizarlo.

Ejemplo:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”
>

Este es el DOCTYPE para una página web escrita en XHTML 1.0 estricto, utilizada para validar miles de páginas web.

[3.2.3]definiciones en un DTD

En un código DTD (tanto externo como interno) se pueden definir:

[3.3] definición de elementos mediante DTD

Mediante un DTD podemos especificar elemento que se puede utilizar en un XML se define en su DTD mediante una etiqueta !ELEMENT. La sintaxis de la misma es:

<!ELEMENT nombre tipo>

Donde:

Los posibles tipos de elementos se explican en el apartado siguientes

[3.3.1]tipos de contenido en los elementos

20EMPTY

Significa que el elemento no podrá tener contenido alguno, es un elemento vacío (como la etiqueta br de las páginas web). Ejemplo de definición de elemento vacío:

<!ELEMENT línea EMPTY >

Cuando se indica como tipo la palabra EMPTY, se indica que el elemento no puede tener contenido. Eso, por cierto, no quiere decir que no podrán contener atributos. Los elementos vacíos pueden tener atributos si así se especifican en el DTD.

Ejemplos de elementos vacíos son:

<línea></línea>

o bien:

<línea />

21ANY

Permite cualquier contenido en el elemento, sin restricciones de ningún tipo. Es decir puede contener texto, otro tipo de datos y cualquier etiqueta. Además puede tener atributos.

Ejemplo:

<?xml version=”1.0”?>
<!DOCTYPE persona [
	<!ELEMENT persona (nombre, apellidos)>
	<!ELEMENT nombre (#PCDATA)>
	<!ELEMENT apellidos ANY>
]>
<persona>
	<nombre>Jorge</nombre>
	<apellidos>Sánchez Asenjo
		<nombre>Jorge</nombre>
	</apellidos>
</persona>

Al definir apellidos como elemento ANY, permite incluso que dentro haya una etiqueta nombre.

Puesto que un DTD se usa para restringir la escritura de un tipo de documentos XML, el uso de ANY debe de ser muy cauteloso.

22contenido concreto

En los elementos se puede indicar que, dentro del mismo, tienen que aparecer un contenido concreto. Dicho elemento se indica entre paréntesis. Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE persona [
	<!ELEMENT persona (nombre)>
	<!ELEMENT nombre (#PCDATA)>	
]>
<persona>
	<nombre>Antonio</nombre>
</persona>

En el ejemplo dentro de un elemento persona obligatoriamente debe de existir una etiqueta nombre (una y sólo una).

No sólo se pueden indicar nombres de elementos como contenido concreto, la indicación #PCDATA significa que el elemento podrá contener texto literal (tan largo como se desee).

El texto de tipo #PCDATA tiene que cumplir las reglas de texto XML. Eso implica que no puede contener símbolos como prohibidos como < o >. En su lugar hay que utilizar entidades.

23secuencias

En el caso de indicar una lista de elementos separados por comas, por ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE persona [
	<!ELEMENT persona (nombre, apellidos, edad)>
	<!ELEMENT nombre (#PCDATA)>	
	<!ELEMENT apellidos (#PCDATA)>	
	<!ELEMENT edad (#PCDATA)>	
]>
<persona>
	<nombre>Antonio</nombre>
	<apellidos>Pérez</apellidos>
	<edad>35</edad>
</persona>

Indica que el elemento contendrá la lista de elementos indicada, la cual deberá estar en el mismo orden especificado en el DTD. Es decir en el ejemplo los apellidos no podrían aparecer antes que el nombre.

24elecciones u opciones

Los elementos pueden contener elementos opcionales (puede aparecer uno u otro). Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE artículo [
	<!ELEMENT artículo (id | serie)>
	<!ELEMENT id (#PCDATA)>
	<!ELEMENT serie (#PCDATA)>
]>
<artículo>
	<id>16</id>
</artículo>

La barra vertical indica que el elemento puede contener una u otra opción (pero sólo una). Es decir también sería válido:

<?xml version=”1.0” encoding=”UTF-8”?>

<!DOCTYPE artículo [
<!ELEMENT artículo (id | serie)>
<!ELEMENT
id (#PCDATA)>
<!ELEMENT serie (#PCDATA)>
]>

<artículo>

	<serie>X1238H</serie>
</artículo>

Si dentro de la lista de opciones queremos indicar PCDATA, éste debe de ser el primer elemento de la lista.

25combinaciones

Por supuesto puede haber combinaciones de definiciones, si tenemos un documento DTD llamado coordenada.dtd con este contenido:

<?xml version=”1.0” encoding=”UTF-8”?>
<!ELEMENT coordenada ((longitud, latitud) | coordUniversal)>
<!ELEMENT longitud (#PCDATA)>
<!ELEMENT latitud (#PCDATA)>
<!ELEMENT coordUniversal (#PCDATA)> 

Sería válido este documento:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE coordenada SYSTEM “coordenada.dtd”>
<coordenada>
	<longitud>234</longitud>
	<latitud>-23</latitud>
</coordenada>

Y sería válido también:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE coordenada SYSTEM “coordenada.dtd”>
<coordenada>
	<coordUniversal>1232332</coordUniversal>
</coordenada>

26cardinalidad

La cardinalidad es el número de veces que puede aparecer un determinado contenido en un elemento. Se realiza mediante estos símbolos:

Ejemplo:

<!ELEMENT película (título, dirección+, 
       argumento?, actor*)>

Según la instrucción anterior el elemento película consta de un título, uno o más elementos de dirección, puede o no tener argumento, y de varios a ningún actor (además se tendría que respetar ese orden). Otro ejemplo (polígono.dtd):

<?xml version=”1.0” encoding=”UTF-8”?>
<!ELEMENT polígono ((coordX,coordY)+ | nombre)>
<!ELEMENT coordX (#PCDATA)>
<!ELEMENT coordY (#PCDATA)>
<!ELEMENT nombre (#PCDATA)>

Con esa DTD sería válido el documento:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE polígono SYSTEM “polígono.dtd”>
<polígono>
	<coordX>12</coordX>
	<coordY>13</coordY>
	<coordX>17</coordX>
	<coordY>23</coordY>
	<coordX>34</coordX>
	<coordY>56</coordY>
</polígono>

Pero también:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE polígono SYSTEM “polígono.dtd”>
<polígono>
	<nombre>Triángulo</nombre>
</polígono>

[3.4] declaración de atributos mediante DTD

Los atributos permiten añadir información a un elemento. Un atributo no puede constar de más atributos y cada atributo sólo puede aparecer una vez en cada elemento.

[3.4.1]sintaxis de la declaración de atributos

Los atributos se declaran mediante la etiqueta !ATTLIST, sintaxis:

<!ATTLIST elemento nombreAtributo tipo presencia   
    valorPorDefecto> 

Donde:

Para indicar el tipo de valores de un atributo, la palabra CDATA sirve para indicar que el atributo contiene texto (CDATA es el acrónimo de Character DATA).

A diferencia de #PCDATA, su contenido no es procesado, lo que significa que puede contener cualquier valor (incluidos símbolos prohibidos en los #PCDATA como <, >, &, etc )

[3.4.3]declarar atributos

Esta declaración:

<!ATTLIST persona nacionalidad CDATA>

Significa que hemos definido el atributo nacionalidad correspondiente al elemento persona. Que será de tipo CDATA, es decir texto normal. Así en un XML que se valide con el DTD anterior, podremos indicar:

<persona nacionalidad=”española”>

[3.4.4]valores

Al declarar un atributo, lo último que se indica es la propiedad relativa al valor por defecto del atributo. Se comentan a continuación como indicar valores.

27valor por defecto concreto

Si al final de la declaración de un atributo aparece un valor concreto, se entiende que ese será el valor por defecto. Es decir, que se podría no utilizar el atributo en un elemento y entonces dicho atributo tomaría dicho valor.

Por ejemplo supongamos que éste es el archivo directorio.dtd:

<?xml version=”1.0” encoding=”UTF-8”?>
<!ELEMENT directorio (persona)+>
<!ELEMENT persona (#PCDATA)>
<!ATTLIST persona nacionalidad CDATA “Española”>

Se define en él el atributo nacionalidad, para el elemento persona, como un atributo que contendrá texto de todo tipo, pero que por defecto toma el valor Española (nacionalidad por defecto en dicho archivo).

Entonces este archivo XML será válido:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE directorio SYSTEM “directorio.dtd”>
<directorio>
<persona
nacionalidad=”Francesa”>
         Vivian Maret
    </persona>
<persona>Juan Martín</persona>
</directorio>

Entonces para Vivian Maret se ha indicado explícitamente la nacionalidad, pero no se ha indicado ese atributo para Juan Martín, por lo que Juan Martían tendrá nacionalidad española.

28valores fijos

Se puede utilizar el término #FIXED para definir un valor fijo para un atributo. Un valor fijo de un atributo no se puede modificar. Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<!ELEMENT directorio (persona)+>
<!ELEMENT persona (#PCDATA)>
<!ATTLIST persona nacionalidad CDATA #FIXED “Española”>

El atributo nacionalidad no podrá tomar ningún valor que no sea el valor Española, impidiendo tomar otra nacionalidad.

En la práctica este tipo de atributos no se usa demasiado, sólo se usa en el caso de atributos que indican alguna información basada en la propia existencia o no de dicho atributo. Es el caso del atributo noshade del elemento hr del lenguaje HTML. hr sirve para dibujar una línea en una página web, la línea se dibuja en relieve salvo que aparezca el atributo noshade, el cual indica la línea tenga formato aplanado. En HTML compatible con XML (lo que se conoce como XHTML) a noshade sólo se le puede dar un valor: la propia palabra noshade:

<hr noshade=”noshade” />

29valores requeridos

En este caso se usa la palabra #REQUIRED indicando con ello que siempre hay que dar valor al atributo. Ejemplo:

<!ATTLIST persona nacionalidad CDATA #REQUIRED>

Un documento XML que utilice el elemento persona deberá especificar obligatoriamente la nacionalidad.

Obviamente, el uso de #REQUIRED no permite indicar un valor por defecto, al no poder dejarse sin especificar el atributo.

30valor opcional

La palabra #IMPLIED especificada en el atributo indicaría que dicho atributo puede quedarse sin valor; es decir no posee valor por defecto, pero puede quedarse sin especificar (quedaría nulo por tanto).

<!ATTLIST persona nacionalidad CDATA #IMPLIED>

En el ejemplo, el atributo nacionalidad no es obligatorio especificarle, puede quedar sin valor. Nuevamente en este caso no se puede especificar un valor por defecto (sería absurdo).

[3.4.5]tipos de atributo

31CDATA

Como se comentó antes, los atributos de tipo CDATA permiten indicar como valor cualquier texto. A diferencia de los datos PCDATA de los elementos, los CDATA admiten cualquier carácter del tipo que sea.

32ID

Sirve para especificar que el atributo contendrá un identificador de elemento. Un identificador es un valor único que tendrá cada elemento y son muy usados en XML.

El valor de un atributo de tipo ID cumple estas reglas:

Los IDs son especialmente útiles para las herramientas de maquetación, análisis y programación de aplicaciones XML. Ya que permiten diferenciar de manera única a cada elemento.

33IDREF

Los atributos IDREF contienen como valor el identificador de otro elemento. Es decir será una referencia a otro elemento. Las reglas de los IDREF son:

La idea es poder relacionar elementos a través de atributos de tipo ID e IDREF. Ejemplo de uso:

<?xml version=”1.0” encoding=”UTF-8”?>
<!-- Archivo directorio.dtd -->
<!ELEMENT directorio (persona)+ >
<!ELEMENT persona (#PCDATA) >
<!ATTLIST persona id ID #REQUIRED madre IDREF #IMPLIED
padre IDREF #IMPLIED>
<?xml version=”1.0” encoding=”UTF-8”?>
<!-- Archivo directorio1.xml-->
<!DOCTYPE directorio SYSTEM “directorio.dtd”>
<directorio>
<persona id=”p1”>Pedro</persona>
<persona id=”p2”>Marisa</persona>
<persona id=”p3” madre=”p2” padre=”p1”>Carmen</persona>
</directorio>

Carmen es la hija de Pedro y Marisa, según el código anterior, ya que los atributos padre y madre de tipo IDREF contienen los ID de Pedro y Marisa.

34IDREFS

Igual que el anterior, solo que, en este caso, se permite indicar varias referencias (que deben existir en el documento XML) a otros ID, separadas por espacios. Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<!-- Archivo directorio.dtd -->
<!ELEMENT directorio (persona)+ >
<!ELEMENT persona (#PCDATA) >
<!ATTLIST persona id ID #REQUIRED
padres IDREFS #IMPLIED >
<?xml version=”1.0” encoding=”UTF-8”?>
<!-- Archivo directorio1.xml-->
<!DOCTYPE directorio SYSTEM “directorio.dtd”>
<directorio>
<persona id=”p1”>Pedro</persona>
<persona id=”p2”>Marisa</persona>
<persona id=”p3” padres=”p1 p2”>Carmen</persona>
</directorio>

35NMTOKEN

El valor del atributo será un texto que cumple reglas estrictas. Concretamente, cumplirá las reglas de los nombres de elementos XML. Se usa en atributos donde se entiende que CDATA permite demasiadas libertades.

Los atributos NMTOKEN contienen texto donde solo existirán letras, números y el símbolo _, es decir un texto que cumple las reglas para nombres XML.

36NMTOKENS

El atributo puede contener varios valores de tipo NMTOKEN separados por espacios.

37ENTITY

El valor de un atributo será una entidad de la cual se indica el nombre. Más adelante se explica el uso de las entidades.

38ENTITIES

El valor del atributo será una lista de nombres de entidades separadas por espacios.

39enumeraciones

Se trata de atributos a los que se indica una serie de posibles valores. El valor del atributo debe coincidir con alguno de la lista. Los valores posibles se indican entre paréntesis separados por el símbolo |.

Ejemplo:

<!ATTLIST persona sexo (Hombre | Mujer) #REQUIRED >

Las personas sólo podrán especificar como sexo “Hombre” o “Mujer” y nada más:

<persona sexo=”Varón”>Javier Ruiz</persona>

El código anterior XML fallaría ya que el atributo sexo no admite el valor “Varón”.

[3.4.6]declaración de varios atributos en la misma etiqueta

Se usa muy habitualmente para indicar de forma cómoda todos los atributos de un determinado elemento:

<?xml version=”1.0” encoding=”UTF-8”?>
<!ELEMENT directorio (persona)+>
<!ELEMENT persona (#PCDATA)>
<!ATTLIST persona nacionalidad CDATA “Española”
sexo (Hombre | Mujer) #IMPLIED
id ID #REQUIRED>

Para ese documento DTD, sería válido este XML:

<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE directorio SYSTEM “directorio.dtd”>
<directorio>
<persona nacionalidad=”Francesa” id=”A1234”>
          Vivian Maret
    </persona>
<persona id=”A789”>Juan Martín</persona>
<persona sexo=”Hombre” id=”A12”>Rafael Díaz</persona>
</directorio>

[3.5] definición de entidades en DTD

Las entidades son elementos XML que permiten indicar abreviaturas de texto (o referencias a elementos externos abreviadas) o utilizar caracteres que de otra forma serían inválidos en el documento.

A continuación se explican sus posibilidades

[3.5.1]entidades ya existentes

En XML están definidas las siguientes entidades:

entidad

significado

&lt;

El símbolo de menor (<)

&gt;

El símbolo de mayor (>)

&amp;

El ampersand: &

&apos;

La comilla simple (‘)

&quot;

La comilla doble (“)

Estas entidades no hay que declararlas en ningún DTD, todos los analizadores de XML estándar conocen estas entidades.

Ejemplo:

<autor>Leopoldo Alas &apos;Clarín&apos;</autor>

El texto PCDATA del autor es Leopoldo Alas ‘Clarín’ (así se visualizará en el navegador).

[3.5.2]entidades para referencias a caracteres especiales

La etiqueta inicial <?xml permite indicar (entre otras cosas) el juego de caracteres que utiliza un documento XML (normalmente Unicode, UTF8).

Si deseamos indicar un carácter especial que no está contenido en nuestro teclado, conociendo su código en el juego de caracteres que utiliza el documento, podemos especificarle con la sintaxis:

&#número;

Donde el número es el código del carácter en decimal. En hexadecimal se puede hacer con:

&#xnúmero;

Ejemplo:

<calle>Kantstra&#223;e, Berlín</calle>

En el navegador este elemento aparecería como:

<calle>Kantstraße, Berlín</calle>

El número se puede poner en hexadecimal si se antecede una x al nombre, por ejemplo sería equivalente:

<calle>Kantstra&#EF;e, Berlín</calle>

[3.5.3]entidades generales

Se usan como abreviaturas que aparecerán en el documento XML. La razón de su uso es facilitar la escritura de nombres repetitivos (nombres de la empresa, direcciones muy utilizadas,…). La sintaxis para declarar una entidad de este tipo es:

<!ENTITY nombre texto>

Para usar en un documento XML la entidad declarada, se usa el formato habitual:

&nombre;

Ejemplo de declaración de una entidad:

<!ENTITY mayor “Calle Mayor Principal” >

Su uso en un documento XML, sería:

<dirección>&mayor; 18</dirección>

La dirección indicada es Calle Mayor Principal 18.

Incluso se pueden indicar símbolos que no son PCDATA al definir entidades:

<!ENTITY negCursiva “<strong><em></em></strong>”>

El documento XML que utilice dicha entidad incluirá todos los símbolos (y por lo tanto estará especificando etiquetas en el código).

Un uso muy interesante es usar entidades que hacen referencia a archivos externos (mediante su dirección URL), por ejemplo:

<!ENTITY direcciónCompleta SYSTEM “direccion.txt” >

Es la palabra SYSTEM la que indica que la entidad no es un texto sino que es el contenido de un archivo. El uso de la entidad &direcciónCompleta; en un documento XML provocará que en dicho documento se añada el contenido del archivo dirección.txt (en la posición exacta en la que esté colocada la referencia a la entidad).

[3.5.4]entidades de parámetros

Solo se pueden utilizar dentro del DTD (no en el documento XML). Su uso más habitual es construir DTD utilizando las entidades definidas a fin de ahorrar trabajo al crear el propio DTD.

Su uso es similar a las entidades generales sólo que utilizan el símbolo % en lugar del símbolo &. Al igual que las generales, deben de ser declaradas antes de poder usarse:

<!ENTITY % mayor “Calle Mayor Principal” >

Y su uso (dentro del DTD), por ejemplo:

<!ATTLIST persona dirección CDATA %mayor;”>

En este caso las comillas dobles son obligatorias porque los valores por defecto van entrecomillados (como se ha visto anteriormente).

Las entidades de parámetros pueden utilizar archivos externos, ejemplo de DTD:

<?xml version=”1.0” encoding=”UTF-8”?>
<!ENTITY % directorio SYSTEM “directorio.dtd” >
%directorio;
<!ELEMENT empresa (razónSocial, dirección) >
<!ELEMENT razónSocial (#PCDATA) >

De esta forma se construye un DTD con el contenido ya especificado en otro DTD. En el ejemplo las empresas constan de elementos razónSocial y de directorio. El elemento directorio no se define, sino que su descripción está especificada en directorio.dtd.

No obstante el uso más habitual es definir una entidad para utilizar código común en el propio DTD, por ejemplo supongamos que dos elementos, profesor y alumno comparten atributos comunes. Entonces este código simplifica la definición de los atributos de esos elementos.

[3.6] validación por XML Schema

[3.6.1]XML Schema y DTD

Los DTD en realidad son una reminiscencia del lenguaje SGML que permite un mecanismo de validación para XML al ser éste un subconjunto de SGML.

Por ello, se planteó en torno a 1999 una sintaxis que permitiera más capacidades de validación y que fuera más coherente con el lenguaje XML. Hoy en día es la arquitectura predominante para la validación, ya que se usa en XQuery y sobre todo en los servicios Web.

[3.6.2]ventajas de los esquemas

Un esquema es un documento XML al que se le coloca la extensión xsd. Al ser un archivo XML tiene la estructura habitual de todo documento XML con la obligación de que el elemento raíz se llame schema.

40etiqueta schema

La etiqueta schema identifica la raíz de un documento XML Schema. En esta etiqueta se declara el espacio de nombres estándar que utilizan los esquemas (y que permite diferenciar las etiquetas XML del esquema, respecto a las del documento XML), el cual se puede definir como el espacio de nombres por defecto, definir un prefijo xs para él (es la forma habitual) o bien definir un prefijo xsd. Es decir estas tres posibilidades:

A partir de ahí las etiquetas pertenecientes a XML Schema, usarán el prefijo indicado en su espacio de nombres. Normalmente se usa la segunda opción, la que implica usar el prefijo xs. En estos apuntes se dará por hecho que hemos utilizado esa segunda opción.

Las etiquetas privadas, las propias de nuestro documento pueden tener asignado un espacio de nombres. Normalmente se le aplica un espacio de nombres por defecto. De esa forma los elementos sin prefijo serán los nuestros y los que tienen prefijo los correspondientes a la sintaxis de XML Schema. Por ejemplo:

<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”
xmlns=”http://www.jorgesanchez.net/doc”
targetNamespace=”http://www.jorgesanchez.net/doc”>

En el ejemplo anterior, las etiquetas correspondientes al espacio estándar de XML Schema usarán el prefijo xs, mientras que las etiquetas pertenecientes a los documentos XML correspondientes al espacio privado de la dirección jorgesanchez.net/doc usarán el espacio de nombres por defecto.

El atributo targetNamespace sirve para indicar a qué espacio de nombres se aplican las normas definidas por XML Schema.

En este otro ejemplo:

<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”
xmlns:doc=”http://www.jorgesanchez.net/doc”
targetNamespace=”http://www.jorgesanchez.net/doc”>

Ahora los elementos de XMLSchema usarán el prefijo xs, mientras que las nuestras etiquetas usan el prefijo doc.

Finalmente veamos un ejemplo más enrevesado:

<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”
xmlns:doc=”http://www.jorgesanchez.net/doc”
xmlns:img=”http://www.jorgesanchez.net/img”
targetNamespace= “http://www.jorgesanchez.net/doc http://www.jorgesanchez.net/img “>

En este último caso, las etiquetas XMLSchema usan el prefijo xs, y nuestras etiquetas usan dos prefijos (puesto que usamos dos espacios de nombres) doc e img. Ambos espacios están también indicados en el targetNamespace; eso indica que el esquema se aplicará a documentos pertenecientes a ambos espacios de nombres.

En todos los casos, a esta etiqueta le siguen los elementos que permiten especificar las reglas de validación del documento XMl Schema.

41asociar un esquema a un documento XML

Para que un documento XML siga las reglas definidas en un esquema, no disponemos de etiqueta !DOCTYPE; en su lugar utilizamos atributos especiales en el elemento raíz del documento XML.

Primero, al igual que en el documento XMLSchema, necesitamos definir los dos espacios de nombres, el correspondiente al documento XML (que se suele usar sin abreviatura, es decir como espacio por defecto) y el espacio de nombres de XML Schema (que suele utilizar el prefijo xs, aunque se puede utilizar otro).

Además es necesario indicar dónde está el archivo XMLSchema que contiene las reglas de validación que se aplican al documento. Esto se hace gracias al atributo llamado schemaLocation (perteneciente al espacio de nombres del esquema, por lo que se usa normalmente como xs:schemaLocation).

Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<documento xmlns=”http://www.jorgesanchez.net/doc”
       xmlns:xs=”http://w3.org/2001/XMLSchema-instance”
       xs:schemaLocation=”esquema.xsd”>
    ....
</documento>

En este código se indica el espacio por defecto de nombres en el documento (coincide con el declarado en el propio archivo del esquema), se indica el espacio de nombres correspondiente al esquema (siempre es la misma URL) y se asocia a este espacio el prefijo xs (se puede elegir otro prefijo, pero no es lo normal).

El atributo schemaLocation (acompañado del prefijo asociado al espacio de nombres de XMLSchema) indica la localización del documento XMLSchema que contiene la definición de las reglas a cumplir por el documento. Es un par formado por el espacio de nombres que será validado por el esquema y por la ruta al documento XMLSchema (con extensión xsd).

Se pueden indicar varios esquemas de validación, por lo que habría que indicar a qué espacio se aplica cada uno:

<?xml version=”1.0” encoding=”UTF-8”?>
<documento xmlns:doc=”http://www.jorgesanchez.net/doc”
 	    xmlns:img=”http://www.jorgesanchez.net/img”
          xmlns:xs=”http://w3.org/2001/XMLSchema-instance”
 		  xs:schemaLocation=
   ”http://www.jorgesanchez.net/doc  esquemaDoc.xsd 
   “http://www.jorgesanchez.net/img  esquemaImg.xsd” 
   .... 
</documento>

La dirección del documento se ha puesto en estilo de ruta relativa, que se calcula a partir de la dirección del documento XML (es decir el documento XMLSchema en el ejemplo estará en la misma carpeta del XML). Pero lo habitual es que a los esquemas se acceda por URL completa; por ejemplo
http://www.obj.com/esq.xsd

Además podemos indicar un esquema para un documento, pero sin que dicho esquema utilice espacio de nombres. Por ejemplo el esquema podría tener esta cabecera (archivo esquema1.xsd):

<?xml version=”1.0” encoding=”UTF-8”?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”>
<xs:element name=”descripción” type=”xs:string” />
</xs:schema>

El archivo XML Schema anterior no indica ningún espacio de nombres al que aplicarse. Un documento que hiciera referencia al esquema podría ser:

<?xml version=”1.0” encoding=”UTF-8”?>
<descripción xmlns:xs=
”http://www.w3.org/2001/XMLSchema-instance”
xs:noNamespaceSchemaLocation=”esquema1.xsd”>
</descripción>

El atributo noNameSchemaLocation permite indicar un esquema para el documento sin que éste utilice espacio de nombres alguno (lo cual no es nada aconsejable, pero vale para hacer pruebas).

42partes de un esquema

El orden de los elementos en un esquema no es significativo, es decir las declaraciones se pueden hacer en cualquier orden. Pero sí que hay que tener en cuenta que dependiendo de dónde coloquemos la definición de los elementos del esquema, varía su ámbito de aplicación. Se distinguen dos posibilidades de declarar elementos:

Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”
xmlns:doc=”http://www.jorgesanchez.net/doc”
targetNamespace=”http://www.jorgesanchez.net/doc”>
<xs:element …>  <!--Definición global
  <xs:simpleType …> <!--Definición local,
  </xs:simpleType>
</xs:element >
<xs:simpleType …> <!--Definición global
</xs:simpleType …>
</xs:schema>

El componente local definido sólo se podría utilizar en la zona resaltada. Si fuera global se podría utilizar en todo el documento.

[3.7.2]sintaxis de la definición de un elemento XML Schema

En XML Schema la definición de un elemento XML se realiza mediante la etiqueta element. La sintaxis completa es:

<xs:element
	name=”nombre del elemento
	type=”tipo global de datos
	ref=”declaración del elemento global
	id=”identificador
	form=”cualificación<!--qualified o unqualified -->
	minOccurs=”número mínimo de veces
	maxOccurs=”máximo número de veces
	default=”valor por defecto
	fixed=”valor fijo
>

Al menos hay que indicar el nombre; el tipo de datos también es necesario indicarle casi siempre; el resto de atributos sólo si se necesitan. Por ejemplo se puede definir un elemento como:

<?xml version=”1.0” encoding=”UTF-8”?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”>
<xs:element name=”descripción” type=”xs:string” />
</xs:schema>

El elemento descripción será de tipo string. Los tipos de datos en XML Schema son muchos y además permiten personalizar sus posibilidades para adaptarles a cualquier necesidad.

Poco a poco todos los atributos de la etiqueta element se irán describiendo a lo largo del presente documento.

[3.7.3]tipos simples de datos

Tenemos dos posibles variantes:

43tipos de datos primitivos

Son los tipos básicos de XML. Sirven para formar los tipos derivados y tipos más complejos.

Para usarlos basta indicarlos en el atributo type de una etiqueta element o attribute (que son las que permiten crear elementos y atributos). De esta forma:

<?xml version=”1.0” encoding=”UTF-8”?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”>
<xs:element name=”descripción” type=”xs:string”/>
</xs:schema>

Él código remarcado es el que indica que en los documentos XML basados en esta plantilla XMLSchema, habrá un elemento llamado descripción que contendrá datos de tipo string. El hecho de que se use el prefijo xs (es decir xs:string) es para indicar que es un tipo XML y por lo tanto usa el prefijo designado al espacio de nombres de XMLSchema. Los tipos básicos son:

1textos
2lógicos
3números
4fechas

Se basan en la especificación ISO 8601.

5especiales

44tipos de datos derivados

Son datos que se han definido a partir de los anteriores, pero forman parte de XMLSchema, es decir que en la práctica se usan igual que los anteriores (al igual que en los primitivos, cuando se usan en un esquema hay que añadir el prefijo del espacio de nombres del esquema, por ejemplo xs:normalizedString).

1textos

2números

45tipos equivalentes a los existentes en el lenguaje DTD

Están basados en los tipos XML 1.0 y sólo pueden utilizarse en atributos (para mantener la compatibilidad con DTD).

46uso de tipos de datos en componentes de XMLSchema

Para que un determinado componente del esquema (como un elemento o un atributo) use uno de los tipos, se dispone del atributo type al que se le indicaría el tipo de datos.

Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”>
xmlns:doc=”http://www.jorgesanchez.net/doc”
targetNamespace=”http://www.jorgesanchez.net/doc”>
<xs:element name=”documento” type=”xs:NCName”/>
<xs:element name=”contenido” type=”xs:string” />
<xs:element name=”precio” type=”xs:decimal” />
</xs:schema>

En el ejemplo se trata de las primeras líneas de un código XMLSchema donde se definen tres elementos, cada uno de los cuales con un tipo distinto. Observar el uso del prefijo xs asignado al espacio de nombres de XMLSchema antes del nombre del tipo de datos.

[3.7.5]definir tipos simples personales

La sintaxis general es:

<xs:simpleType name=”nombre”>
	...definición del tipo....
</xs:simpleType>

47definir tipos por unión

Se trata de utilizar dentro del tipo de datos una etiqueta llamada union que permite unir las definiciones de dos tipos de datos. Por ejemplo:

<xs:simpleType name=”gMonthC”>
<xs:union
memberTypes=”xs:gMonth xs:gMonthDay” />
</xs:simpleType>

Cuando a cualquier elemento del esquema se le asigne el tipo gMonthC, se podrán especificar datos en formato gMonth y en formato gMonthDay.

[3.7.6]establecer restricciones para tipos simples

Permiten establecer reglas complejas que deben de cumplir los datos. En este caso dentro de la etiqueta simpleType se indica una etiqueta restriction, dentro de la cual se establecen las posibles restricciones. Sintaxis:

<xs:simpleType name=”nombre”>

	<xs:restriction base=”tipo>
		...definición de la restricción....
	<xs:restriction>
</xs:simpleType>

El atributo base sirve para indicar en qué tipo nos basamos al definir la restricción (es decir de qué tipo estamos creando este derivado). El apartado restriction pueden tener numerosas etiquetas que permiten establecer las restricciones deseadas al tipo.

Las etiquetas interiores a restriction disponen de un atributo llamado fixed que sólo puede valer verdadero (true) o falso (false). En caso de que sea verdadero, ningún tipo derivado del definido puede modificar la propiedad establecida; es decir, si establecemos minLength (tamaño mínimo) con valor ocho (propiedad value) y fixed=”true”, ningún tipo derivado del definido podrá definir que el tamaño mínimo sea inferior a 8 caracteres. Es un atributo de uso opcional.

Las posibles restricciones que se pueden establecer son:

Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”
xmlns:doc=”http://www.jorgesanchez.net/doc”
targetNamespace=”http://www.jorgesanchez.net/doc”>
 <xs:simpleType name=”nombresTipo”>
    <xs:restriction base=”xs:normalizedString”>
         <xs:maxLength value=”15” />
         <xs:minLength value=”4” />
     </xs:restriction>
 </xs:simpleType>
 <xs:element name=”título” type=”doc:nombresTipo” />

En e archivo anterior, se define un elemento llamado prueba que tiene un tipo que colapsa los espacios en blanco y así en un documento XML que aplique este esquema, por ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<prueba xmlns:xs=
          ”http://www.w3.org/2001/XMLSchema-instance”
xs:noNamespaceSchemaLocation=”prueba.xsd”>
Este es el texto
que deseo

probar
</prueba>

Cuando mostremos el resultado en un programa que aplique el esquema (por ejemplo en las últimas versiones de Internet Explorer, Firefox, Safari o Chrome), tendremos el contenido de la etiqueta prueba en esta forma:

Este es el texto que deseo probar

Símbolo

Significado

texto tal cual

Hace que sólo se pueda escribir ese texto. Por ejemplo si se indica “Hombre”, la restricción será escribir como valor posible exactamente el texto Hombre.

[xyz]

Permite elegir entre los caracteres x, y o z

[^xyz]

Prohíbe usar cualquiera de los caracteres entre corchetes

[a-z]

Vale cualquier carácter de la a, a la z.

^

Inicio de línea

$

Final de línea

+

Repite acepta el carácter precedente una o más veces

?

Acepta el carácter precedente 0 o más veces

*

Acepta el carácter precedente una o más veces

{n}

Acepta exactamente n repeticiones del carácter precedente.

{n,}

Acepta al menos n repeticiones del carácter precedente.

{n,o}

Acepta entre n y o repeticiones del carácter precedente.

\s

Permite indicar los caracteres especiales. Por ejemplo \^ representa el carácter circunflejo ^ para que sea tomado como texto y no como código especial.

Por ejemplo la validación para un dato tipo DNI (8 cifras y un número), sería:

<xs:simpleType name=”dniTipo”>
<xs:restriction
base=”xs:string”>
<xs:whiteSpace
value=”collapse” />
<xs:pattern
value=”[0-9]{8}[A-Z]” />
</xs:restriction>
</xs:simpleType>

Las listas permiten que un componente tenga como contenido una determinada lista de valores. la construcción de listas indica dos pasos:

[1]Crear un tipo simple de datos cuyo contenido es una etiqueta list, la cual posee el atributo itemType para indicar el tipo de elementos de la lista. Simplemente con ello e podría establecer una lista (valores separados por espacios) de valores pertenecientes al tipo indicado.

[2]Crear el tipo ya definitivo de datos que contendrá una etiqueta restriction a la cual como tipo base se indica el tipo simple de datos relacionado con la lista. EN la restricción se pueden indicar estas etiquetas usando el atributo value:

[3]Es decir, son las etiquetas ya conocidas, pero que ahora se refieren a la lista. Ejemplo:

<xs:simpleType name=”listaDecimales”>
<xs:list
itemType=”xs:decimal” />
</xs:simpleType>
<xs:simpleType name=”listaNotas”>
<xs:restriction
base=”listaDecimales”>
<xs:minLength
value=”3” />
<xs:maxLength
value=”6” />
</xs:restriction>
</xs:simpleType>

[4]Primero se define un tipo de lista (listaDecimales) simplemente indicando que será una lista cuyos valores serán números decimales. Después se concreta la lista (listaNotas), de modo que ahora se indica que la lista constará de tres a seis números (en el XML cada número irá separado por espacios)

[3.7.8]definiciones locales de tipos

Como se comentó anteriormente, los componentes de XML Schema pueden definirse en modo local o global. En modo global cualquier otro componente le puede utilizar, en modo local sólo aquel que contiene la definición. Los datos simples se pueden crear, por ejemplo, en un elemento y así se aplican sólo a dicho elemento.

Ejemplo:

<xs:element name=”elemento1”>
<xs:simpleType>
<xs:restriction base=”xs:string”>
<xs:whiteSpace
value=”collapse” />
<xs:maxLength
value=”16” />
</xs:restriction>
</xs:simpleType>

</xs:element>

El tipo simple declarado ni siquiera tiene nombre, ya que no se utilizará fuera del elemento elemento1.

[3.7.9]definición de atributos en XML Schema

Los atributos se definen parecido a los elementos. Su sintaxis de definición es:

<xs:attribute
	name=”nombre del elemento
	type=”tipo global de datos
	ref=”declaración del elemento global
	form=”cualificación<!--qualified o unqualified 
	id=”identificador
              default=”valor por defecto
	fixed=”valor fijo
	use=”uso” <!-- prohibited, optional o required 
>

Los atributos sólo pueden asignarse a los elementos mediante tipos complejos de datos. El uso hace referencia a si al atributo no se le puede asignar ningún valor en el documento XML (valor prohibited), si su uso es opcional (valor optional) o si es obligatorio darle valor.

[3.7.10]tipos compuestos

Los tipos de datos del apartado anterior sólo sirven para indicar contenidos simples (que contienen sólo información en el interior) de elementos o bien para indicar posibles valores a los atributos. Los tipos compuestos permiten definir contenidos más complejos. Puesto que lo normal es que los elementos de un documento XML puedan contener otros elementos y por supuesto atributos, es lógico que la mayoría de elementos indiquen mediante tipos compuestos su contenido. Los datos simples son apropiados para indicar el tipo de contenido de los atributos o bien para indicar el contenido de los elementos simples (lo que en DTD serían elementos sólo con contenido # PCDATA).

Al igual que los datos simples, los compuestos pueden ser globales o locales. En el caso de ser locales no se indica un nombre (atributo name) y entonces sólo se podrán utilizar para el elemento en el que se definieron. Los globales se pueden utilizar para distintos elementos y por lo tanto requieren que se indique su nombre.

Los tipos compuestos se definen con la etiqueta complexType. En esa etiqueta podemos utilizar diferentes modelos de definición de contenidos.

En realidad los elementos XML desde el punto de vista de la sintaxis XML Schema pueden tener cuatro tipos de contenido:

La sintaxis de la etiqueta complexType admite señalar contenidos simples y compuestos. Para los vacíos y mixtos hay que utilizar (se verá más adelante) atributos especiales en la etiqueta element. Sin indicar nada especial, compexType parte de que estamos definiendo contenidos complejos (es decir, elementos que contienen más elementos).

Los elementos pueden contener atributos, más adelante se indica la forma de incorporarlos.

48elementos vacíos

Para indicar que un elemento es vacío basta con no indicar valores e indicar el nombre del elemento sin indicar tipo de datos alguno.

Ejemplo:

<xs:element name=”casado” >
<xs:complexType>
<xs:attribute
name=”valor” type=”xs:string” />
</xs:complexType>
</xs:element>

En este caso el elemento caso sólo dispone de un atributo llamado valor, no será posible meter ningún contenido en la etiqueta de casado. Si no deseamos atributos (aunque es muy extraño), entonces simplemente no habrá etiquetas attribute (pero sí todas las demás).

49definición de contenidos con texto

Se trata de usar la etiqueta <xs:element al estilo que se ha usado en los ejemplos. Es decir se indica el nombre y el tipo de datos e incluso se pueden indicar atributos dentro del apartado complexType, pero nunca se ponen elementos dentro de este elemento y así sólo se admitirá por contenido el texto (tipo PCDATA).

Ejemplo:

<xs:element name=”nombre” type=”xs:string” />

50definición de contenidos con texto y atributos

En este caso se indica que el elemento posee contenido simple en la etiqueta complexType dentro de la cual se indican los atributos, mientras que es la etiqueta del contenido simple (simpleContent) la que poseerá el tipo de datos para el contenido del elemento.

Hay dos formas de indicar contenido simple: por extensión (mediante etiqueta extension) y por restricción (etiqueta restriction).

Los atributos se deben indicar en el apartado extension que es el encargado de indicar los tipos .

Ejemplo:

<xs:element name=”documento”>
<xs:complexType>
<xs:simpleContent>
<xs:extension
base=”xs:string”>
<xs:attribute
name=”idioma”
                             type=”xs:string” />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>

En el ejemplo, documento es un elemento de tipo string (texto) que contiene un atributo llamado idioma (también string). Es un poco enrevesado, pero es necesario hacerlo así.

[3.7.11]definición de contenidos compuestos

Como se ha comentado antes, los contenidos compuestos se refieren a los elementos que contienen otros elementos (pero nunca texto libre). Hay tres posibles tipos de elementos a contener: secuencias, elecciones y contenidos libres (all). Además se pueden incorporar atributos.

51secuencias

Dentro de un elemento es habitual indicar su contenido como una secuencia de elementos. Esto se permite con la etiqueta sequence, dentro de la cual se añaden etiquetas element para indicar los elementos que entran en la secuencia.

Ejemplo:

<xs:simpleType name=”emailT”>
<xs:restriction base=”xs:string”>
<xs:pattern value=”[A-Za-z]{3,}@.{3,}” />
</xs:restriction>
</xs:simpleType>
<xs:element
name=”email”>
<xs:complexType >
    <xs:sequence>
<xs:element
name=”remite” type=”emailT” />
<xs:element name=”para” type=”emailT” minOccurs=”1” maxOccurs=”unbounded” />
<xs:element name=”CC” type=”emailT” minOccurs=”0” maxOccurs=”unbounded” />
<xs:element name=”CCO” type=”emailT” minOccurs=”0” maxOccurs=”unbounded” />
</xs:sequence>
 </xs:complexType>        
</xs:element>

En el ejemplo, el elemento email está compuesto de cuatro elementos. El remite (que tiene obligatoriamente que aparecer una vez), el para que aparecerá al menos una vez y que puede aparecer tantas veces como se desee y los apartados opcionales CC y CCO que pueden aparecer repetidos.

La etiqueta sequence posee los atributos minOccurs y maxOccurs para indicar que el bloque de la secuencia se puede repetir.

52elecciones

Sirven para permitir elegir uno de entre varios elementos. Su funcionamiento es el mismo que en las secuencias, pero en este caso se utiliza una etiqueta llamada choice.

Ejemplo:

<xs:element name=”identificación”>
<xs:complexType>
<xs:choice>
<xs:element
name=”firma” type=”xs:NCName” />
<xs:element name=”código” type=”xs:NCName” />
</xs:choice>
</xs:complexType>
</xs:element>

En el ejemplo, el elemento identificación, consta de dos posibles elementos firma y código de los que sólo se podrá incluir uno.

La etiqueta choice también posee los atributos minOccurs y maxOccurs.

53etiqueta all

Se trata de una posibilidad similar a choice y sequence que se utiliza de la misma forma y que tiene como diferencia principal que los elementos que contiene pueden aparecer cero o una vez y además en el orden que quieran.

Ejemplo:

<xs:element name=”identificación”>
<xs:complexType>
<xs:all>
<xs:element name=”firma” type=”xs:NCName”/>
<xs:element name=”código” type=”xs:NCName” />
</xs:all>
</xs:complexType>
</xs:element>

En este caso la firma y el código pueden aparecer o no, aparecer los dos e incluso el orden será indiferente. Es una etiqueta muy potente que ahorra mucho trabajo.

Esta etiqueta tiene los atributos minOccurs y maxOccurs, pero sólo se puede indicar como valores cero o uno.

54mezcla de elementos

A veces los contenidos de un documento XML son extremadamente complejos y por eso se permite en los esquema colocar etiquetas choice dentro de etiquetas sequence y viceversa. Y lo mismo ocurre con las etiquetas all. Estas posibilidades permiten crear cualquier tipo de esquema por complejo que resulte.

Ejemplo:

<xs:element name=”correo”>
<xs:complexType>
<xs:sequence>
<xs:element
name=”remite” type=”xs:string”/>
<xs:element
name=”para” type=”xs:string”
minOccurs=
”1” maxOccurs=”unbounded”/>
<xs:choice>
<xs:element
name=”cc” type=”xs:string”
minOccurs=
”1” maxOccurs=”unbounded” />
<xs:element
name=”cco” type=”xs:string”
minOccurs=
”1” maxOccurs=”unbounded” />
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>

En el ejemplo, el elemento correo consta de tres elementos: remite, para y un tercero que puede ser cc o cco.

55añadir atributos

En los apartados complexType, los atributos del elemento se definen al final del apartado complexType (justo antes de cerrarle). Ejemplo:

<xs:element name=”persona”>
<xs:complexType>

<xs:sequence>
<xs:element
name=”nombre” type=”xs:string” />
<xs:element
name=”apellidos” type=”xs:string” />
</xs:sequence>

<xs:attribute
name=”sexo”>
<xs:simpleType>
<xs:restriction
base=”xs:string”>
<xs:enumeration
value=”Hombre” />
<xs:enumeration
value=”Mujer” />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute
name=”fechaNacimiento”
type=
”xs:date” use=”required” />
</xs:complexType>
</xs:element>

Las personas contienen dos elementos en secuencia (nombre y apellidos) y dos atributos: uno opcional (sexo) que sólo pueden tomar los valores Hombre o Mujer y uno obligatorio para la fecha de nacimiento

[3.7.12]contenidos mixtos

Es el caso más complejo. Se trata de elementos que contienen otros elementos y además texto (e incluso atributos). Para permitir esta posibilidad hay que marcar el atributo mixed de la etiqueta complexType a true.

Ejemplo:

<xs:element name=”documento”>
<xs:complexType
mixed=”true”>
<xs:choice>
<xs:element
name=”negrita” type=”xs:string”
minOccurs=
”0” maxOccurs=”unbounded”/>
</xs:choice>
<xs:attribute
name=”lenguaje” type=”xs:language” />
</xs:complexType>
</xs:element>

Lo malo es que no se puede controlar el tipo de datos del texto interior. Los elementos se controlan completamente, pero el texto no.

[3.7.13]uso de elementos y atributos globales

Se trata de definir un elemento o un atributo para ser reutilizado en diferentes partes del documento. La forma de utilizarlos es:

Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”>
<xs:element
name=”email”>
<xs:simpleType>
<xs:restriction
base=”xs:string”>
<xs:pattern
value=”[A-Za-z]{3,}@.{3,}” />
        </xs:pattern>
      </xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element
name=”trabajador”>
<xs:complexType>
<xs:sequence>
<xs:element
name=”nombre” type=”xs:string” />
<xs:element
name=”apellidos” type=”xs:string” />
<xs:element
ref=”email” minOccurs=”1”
				maxOccurs=”unbounded” />
</xs:sequence>

</xs:complexType>
</xs:element>
</xs:schema>

En este caso se ha definido un elemento global llamado email que representa una dirección de email (dentro se define un tipo simple para restringir la forma en la que se debería rellenar un email) y que después el elemento trabajador la reutiliza para indicar los correos electrónicos de un trabajador. Otros elementos podrían reutilizar esta misma definición.

[3.7.14]grupos de elementos

La etiqueta group permite realizar grupos de elementos y eso permite organizarse mejor a la hora de crear un esquema. Dentro de cada grupo podemos utilizar etiquetas sequence, choice y all de la misma forma que la vista anteriormente y así después utilizar el grupo en la forma deseada. Muchas veces los grupos se definen de forma global y así se pueden utilizar en distintos elementos; pero es posible definirles localmente (suele tener menos interés hacerlo en local).

Los grupos cuando se definen de forma global requieren indicar un nombre para ellos (si se definen de forma local no). Cuando un elemento desea incorporar un grupo global, utiliza la etiqueta group y con el atributo ref indicaría el nombre del elemento global definido anteriormente. Pueden contener los atributos minOccurs, maxOccurs para indicar las veces que puede repetirse el grupo en el elemento que le contiene. Ejemplo:

<?xml version=”1.0” encoding=”UTF-8”?>
<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”>
<xs:group name=”seccionesCorreo”>
<xs:sequence>
<xs:element name=”remite” type=”xs:string”/>
<xs:element name=”para” type=”xs:string”
                  minOccurs=”1” maxOccurs=”unbounded”/>
<xs:choice>
<xs:element name=”cc” type=”xs:string”
                   minOccurs=”1” maxOccurs=”unbounded” />
<xs:element name=”cco” type=”xs:string”
                   minOccurs=”1” maxOccurs=”unbounded” />
</xs:choice>
</xs:sequence>
</xs:group>
<xs:element name=”correo”>
<xs:complexType>
<xs:sequence>
<xs:group ref=”seccionesCorreo” />
<xs:element name=”contenido” type=”xs:string” />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

[3.7.15]grupos de atributos

La idea es la misma que con los grupos de elementos: facilitar la escritura del código del esquema. Se trata de definir (lo lógico es de forma global) una serie de atributos que utilizan diferentes elementos y así mejorar el mantenimiento del esquema XML.

Los grupos de atributos se declaran con attributeGroup, al definir se utiliza el nombre y al usarle en un elemento se hace referencia a dicho nombre mediante la etiqueta ref.

Ejemplo:

<xs:schema xmlns:xs=”http://www.w3.org/2001/XMLSchema”>
<xs:attributeGroup
name=”infoDoc”>
<xs:attribute
name=”lenguaje” type=”xs:language”
use=
”required” />
<xs:attribute
name=”tamaño”>
<xs:simpleType>
<xs:restriction
base=”xs:positiveInteger”>
<xs:minExclusive value=”20” />
<xs:maxExclusive
value=”200” />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name=”título” type=”xs:string”
                  use=”required”/>
</xs:attributeGroup>

<xs:element
name=”documento”>
<xs:complexType>
<xs:simpleContent>
<xs:extension base=”xs:string”>
<xs:attributeGroup
ref=”infoDoc” />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>

<xs:element
name=”documentoRef”>
<xs:complexType>
<xs:attributeGroup
ref=”infoDoc” />
<xs:attribute
name=”referencia”
             type=”xs:positiveInteger” use=”required” />
</xs:complexType>
</xs:element>


  <xs:element name=”documentos”>
<xs:complexType>
<xs:choice
minOccurs=”1” maxOccurs=”unbounded”>
<xs:element
ref=”documento” />
<xs:element
ref=”documentoRef” />
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>

Se define en el ejemplo un grupo de atributos globales que se llama infoDoc y que está formado por tres atributos (lenguaje, tamaño y título) que se definen completamente en el grupo. Después dos elementos (documento y documentoRef) utilizan el grupo de atributos como si fuera un solo atributo. De modo que un XML basado en este esquema y válido podría ser:

<?xml version=”1.0” encoding=”UTF-8”?>
<documentos
xmlns:xs=
”http://www.w3.org/2001/XMLSchema-instance”
xs:noNamespaceSchemaLocation=
”correo.xsd” >
<documento lenguaje=”es” tamaño=”123”
               título=”Informe 32” />
<documento
lenguaje=”es” tamaño=”34”
               título=”Alta 34” />
<documentoRef lenguaje=”es” referencia=”3234”
título=
”Informe 56” />
</documentos>