Esquemas (III)

DECLARACIONES <CHOICE>

La estructura básica de <choice> se parece mucho a la de <sequence>. Por ejemplo:

<choice> <element name="nombre" type="string" minOccurs="1" maxOccurs="unbounded"/> <element name="apellido1" type="string" minOccurs="1" maxOccurs="1"/> <element name="apellido2" type="string" minOccurs="1" maxOccurs="1"/> </choice>

Sin embargo solo uno de los elementos puede usarse. Es decir, en este modelo de contenido solo puede haber un nombre, o un apellido1 o un apellido2.

Al igual que <sequence>, <choice> permite que se defina una cardinalidad, y puede contener:

  • declaraciones de elemento,
  • secuencias,
  • declaraciones <choice> y
  • referencias a <group>

Un ejemplo:

<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.ejemplo.com" targetNamespace="http://www.ejemplo.com" elementFormDefault="qualified"> <xs:element name="producto"> <xs:complexType> <xs:choice> <xs:sequence> <xs:element name="id" type="xs:string"/> <xs:element name="numero_referencia" type="xs:string"/> </xs:sequence> <xs:element name="nombre_completo" type="xs:string"/> <xs:choice> <xs:element name="descripcion" type="xs:string"/> <xs:element name="ubicacion" type="xs:string"/> </xs:choice> </xs:choice> </xs:complexType> </xs:element> </xs:schema>

En el ejemplo anterior se han utilizado colores diferentes, para resaltar cada una de las opciones. Se muestra un elemento llamado producto que contiene una de tres cosas:

  • O bien un id y un número de referencia,
  • o bien el nombre completo,
  • o bien una descripción o una ubicación

Así, por ejemplo, la siguientes instancias serían válidas:

<?xml version="1.0"?> <producto xmlns="http://www.ejemplo.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/contactos producto.xsd"> <descripcion>Tarjeta PCI controladora de USB con 4 puertos, modelo RTL-6526-PCI.</descripcion> <producto>

<?xml version="1.0"?> <producto xmlns="http://www.ejemplo.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/contactos producto.xsd"> <id>RTL-6526-PCI.</id> <num_ref>R.6526-U<numero_referencia> <producto>

REFERENCIAS A <GROUP>

Las referencias a <group> permiten hacer referencia a elementos <group> globales. La idea es crear modelos de contenido basados en grupos y luego reusarlos dentro de otros elementos. Por ejemplo:

<?xml version="1.0"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:target="http://www.example.com/persona" targetNamespace="http://www.example.com/persona" elementFormDefault="qualified"> <group name="GrupoNombre"> <sequence> <element name="nombre" type="string"/> <element name="apellido1" type="string"/> <element name="apellido2" type="string"/> </sequence> </group> <element name="persona"> <complexType> <group ref="target:GrupoNombre" minOccurs="1" maxOccurs="unbounded"/> <attribute name="título" type="string"/> </complexType> </element> </schema>

De este modo, una instancia válida sería:

<?xml version="1.0"?> <persona xmlns="http://www.example.com/persona" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/persona persona.xsd" titulo="D."> <nombre>Juan</nombre> <apellido1>García</apellido1> <apellido2>Pérez</apellido2> </persona>

Si te fijas bien, comprobarás que ya hicimos referencia a grupos cuando definimos las declaraciones <group>. En el ejemplo, nos referimos a un grupo global llamado "GrupoNombre", mediante la referencia ref="target:GrupoNombre". Dentro de la etiqueta <group> se puede incluir información sobre cardinalidad, es decir, "minOccurs" y "maxOccurs". En el ejemplo, decimos que una persona puede tener muchos nombres (maxOccurs="unbounded", es un poco raro pero ilustra bien su uso). Como siempre, hay que poner prefijo al nombre del grupo, ya que hay que identificar el espacio de nombres en el que la declaración "GrupoNombre" aparece.

DECLARACIONES <ALL>

La declaración <all> nos permite declarar que los elementos dentro de nuestro modelo de contenido pueden aparecer en cualquier orden. <all> soporta información sobre cardinalidad con minOccurs y maxOccurs. Para usar <all> hay que seguir unas cuantas reglas:

  • La declaración <all> debe ser el único modelo de contenido que aparece como hijo de una declaración <complexType>.
  • La declaración <all> puede contener solo declaraciones <element> como hijo. No se permiten declaraciones <sequence>, <choice> o <group>.
  • La cardinalidad en una declaración <all> está limitada a 0 o 1.

Aunque tienen "más reglas el baloncesto", los elementos <all> son útiles cuando se conoce el contenido, pero no el orden de un cierto contenido.

NOTA: Todas estas restricciones se aseguran de que los validadores puedan entender fácilmente los documentos instancia. Sin estas restricciones podría ser difícil escribir software para validar los esquemas con declaraciones <all>.

Veamos un ejemplo:

<element name="persona"> <complexType> <all> <element name="nombre" type="string"/> <element name="apellido1" type="string"/> <element name="apellido2" type=string"/> </all> <attribute name="título" type="string"/> </complexType> </element>

Observa que el ejemplo cumple las reglas citadas anteriormente. La primera regla se cumple, teniendo en cuenta que <attribute> no cuenta como modelo de contenido (no es contenido sino un atributo). La segunda regla también se cumple, ya que solo hay declaraciones <element>. La tercera regla, también, ya que por defecto la cardinalidad es minOccurs="1" y maxOccurs="1".

Así pues, para este modelo de contenido se podrían validar las siguientes instancias:

<apellido2> Pérez </apellido2> <nombre> Juan </nombre> <apellido1> García </apellido1>

VAMOS A VER UN EJEMPLO CON TODO ESTO JUNTO

¿Recuerdas el ejemplo de agenda que hicimos con DTDs, pues ahora lo vamos a hacer con esquemas. Primero el esquema:

<?xml version="1.0"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:contactos="http://www.example.com/contactos" targetNamespace="http://www.example.com/contactos" elementFormDefault="qualified"> <element name="contactos"> <complexType> <sequence> <element name="contacto" minOccurs="0" maxOccurs="unbounded"> <complexType> <sequence> <element name="persona" type="contactos:TipoPersona"/> <element name="localización" type="contactos:TipoLocalización"/> <element name="teléfono" type="string"/> <element name="conocidos" type="contactos:TipoConocidos"/> <element name="descripción" type="contactos:TipoDescripción"/> </sequence> </complexType> </element> </sequence> </complexType> </element> <complexType name="TipoPersona"> <group ref="contactos:GrupoPersona"/> </complexType> <group name="GrupoPersona"> <sequence> <element name="nombre" type="string" minOccurs="1" maxOccurs="unbounded"/> <element name="apellido1" type="string" minOccurs="0" maxOccurs="1"/> <element name="apellido2" type="string"/> </sequence> </group> <complexType name="TipoLocalización"> <choice minOccurs="0" maxOccurs="unbounded"> <element name="dirección" type="string"/> <sequence> <element name="latitud" type="string"/> <element name="longitud" type="string"/> </sequence> </choice> </complexType> <complexType name="TipoConocidos"> </complexType> <complexType name="TipoDescripción" mixed="true"> <choice minOccurs="0" maxOccurs="unbounded"> <element name="em" type="string"/> <element name="strong" type="string"/> <element name="br" type="string"/> </choice> </complexType> </schema>

Y ahora una instancia para este esquema.

<?xml version="1.0"?> <contactos xmlns="http://www.example.com/contactos" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/contactos contactos.xsd"> <contacto> <persona> <apellido2>García</apellido2> <nombre>José</nombre> <apellido1>Pérez</apellido1> </persona> <localización> <dirección>Ciudad Intermedia, España</dirección> <latitud>34.031892</latitud> <longitud>3.207642</longitud> </localización> <teléfono>955-123-456</teléfono> <conocidos/> <descripción>José es el director de <em>una sucursal</em>.<br/>José es <strong> buena persona </strong></descripción> </contacto> <contacto> <persona> <nombre>Antonio</nombre> <apellido1>Pérez</apellido1> <apellido2>Gutiérrez</apellido2> </persona> <localización> <dirección>Mordor, España</dirección> <latitud>34.123323</latitud> <longitud>4.673839</longitud> </localización> <teléfono>956-654-321</teléfono> <conocidos/> <descripción>Antonio es el apoderado de <em>una sucursal</em>.<br/> A Antonio <strong> le gusta su trabajo </strong></descripción> </contacto> </contactos>

Ejercicio 6. Lee detenidamente el esquema y comprueba que lo entiendes todo. Luego lee la instancia y comprueba que el documento es correcto. Valídalo.

Ejercicio 7. Modifica el esquema anterior, para se puedan poner el nombre, apellido1 y apellido2 en cualquier orden, y que el apellido2 sea opcional.

Entrega el esquema con el nombre Act7-esquemas.xsd

Saludos.