En este capítulo se demostrará cómo escribir un esquema XML. También aprenderá que un esquema puede escribirse de diferentes maneras.
Un documento XML
Vamos a echar un vistazo a este documento XML llamado "shiporder.xml" :
<?xml version="1.0" encoding="UTF-8"?>
<shiporder orderid="889923"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="shiporder.xsd">
<orderperson>John Smith</orderperson>
<shipto>
<name>Ola Nordmann</name>
<address>Langgt 23</address>
<city>4000 Stavanger</city>
<country>Norway</country>
</shipto>
<item>
<title>Empire Burlesque</title>
<note>Special Edition</note>
<quantity>1</quantity>
<price>10.90</price>
</item>
<item>
<title>Hide your heart</title>
<quantity>1</quantity>
<price>9.90</price>
</item>
</shiporder>
El documento XML anterior consiste en un elemento de la raíz, "shiporder" , que contiene un atributo necesario llamado "orderid" . El "shiporder" elemento contiene tres diferentes elementos hijo: "orderperson" , "shipto" y "item" . El "item" elemento aparece dos veces, y contiene un "title" , una opción "note" elemento, una "quantity" , y un "price" elemento.
La línea anterior: xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" le dice al analizador XML que este documento debe ser validada con un esquema. La línea: xsi: noNamespaceSchemaLocation = "shiporder.xsd" especifica el lugar donde reside el esquema (here it is in the same folder as "shiporder.xml") .
Crear un esquema XML
Ahora queremos crear un esquema para el documento XML anterior.
Comenzamos con la apertura de un nuevo archivo que llamaremos "shiporder.xsd" . Para crear el esquema podríamos simplemente seguir la estructura del documento XML y definir cada elemento como lo encontramos. Vamos a empezar con la declaración XML estándar seguido de la xs: element esquema que define un esquema:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
...
</xs:schema>
En el esquema anterior se utiliza el espacio de nombres estándar (xs) , y el URI asociado a este espacio de nombres es la definición del lenguaje de esquema, que tiene el valor estándar de http://www.w3.org/2001/XMLSchema.
A continuación, tenemos que definir el "shiporder" elemento. Este elemento tiene un atributo y contiene otros elementos, por lo cual consideramos como un tipo complejo. Los elementos secundarios del "shiporder" elemento está rodeado por un xs: elemento de secuencia que define una secuencia ordenada de elementos sub:
<xs:element name="shiporder">
<xs:complexType>
<xs:sequence>
...
</xs:sequence>
</xs:complexType>
</xs:element>
Entonces tenemos que definir el "orderperson" elemento como un tipo simple (porque no contiene ningún atributo o de otros elementos). El tipo (xs:string) es precedido por el prefijo de espacio de nombres asociado con el esquema XML que indica un esquema predefinido tipo de datos:
<xs:element name="orderperson" type="xs:string"/>
A continuación, tenemos que definir dos elementos que son del tipo complejo: "shipto" y "item" . Comenzamos definiendo la "shipto" elemento:
<xs:element name="shipto">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Con esquemas podemos definir el número de posibles ocurrencias de un elemento con los maxOccurs y atributos minOccurs. maxOccurs especifica el número máximo de ocurrencias de un elemento y minOccurs especifica el número mínimo de ocurrencias de un elemento. El valor predeterminado para ambos maxOccurs y minOccurs es 1!
Ahora podemos definir el "item" elemento. Este elemento puede aparecer varias veces dentro de un "shiporder" elemento. Esto se especifica mediante el establecimiento de la maxOccurs atributo del "item" elemento "unbounded" lo que significa que no puede haber tantas ocurrencias del "item" elemento como desee el autor. Observe que la "note" elemento es opcional. Hemos especificado esta configurando los minOccurs atribuyen a cero:
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string" minOccurs="0"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:element>
Ahora podemos declarar el atributo de la "shiporder" elemento. Dado que este es un atributo necesario especificamos uso = "required".
Note: Las declaraciones de atributos siempre deben ir en último lugar:
<xs:attribute name="orderid" type="xs:string" use="required"/>
Aquí está la lista completa del archivo de esquema llamado "shiporder.xsd" :
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="shiporder">
<xs:complexType>
<xs:sequence>
<xs:element name="orderperson" type="xs:string"/>
<xs:element name="shipto">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string" minOccurs="0"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="orderid" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
Se divide el esquema
El método de diseño anterior es muy simple, pero puede ser difícil de leer y mantener cuando los documentos son complejas.
El siguiente método de diseño se basa en la definición de todos los elementos y atributos en primer lugar, y luego referirse a ellos mediante el ref atributo.
Aquí está el nuevo diseño del archivo de esquema ("shiporder.xsd") :
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- definition of simple elements -->
<xs:element name="orderperson" type="xs:string"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="address" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
<xs:element name="title" type="xs:string"/>
<xs:element name="note" type="xs:string"/>
<xs:element name="quantity" type="xs:positiveInteger"/>
<xs:element name="price" type="xs:decimal"/>
<!-- definition of attributes -->
<xs:attribute name="orderid" type="xs:string"/>
<!-- definition of complex elements -->
<xs:element name="shipto">
<xs:complexType>
<xs:sequence>
<xs:element ref="name"/>
<xs:element ref="address"/>
<xs:element ref="city"/>
<xs:element ref="country"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="item">
<xs:complexType>
<xs:sequence>
<xs:element ref="title"/>
<xs:element ref="note" minOccurs="0"/>
<xs:element ref="quantity"/>
<xs:element ref="price"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="shiporder">
<xs:complexType>
<xs:sequence>
<xs:element ref="orderperson"/>
<xs:element ref="shipto"/>
<xs:element ref="item" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute ref="orderid" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
Uso de tipos con nombre
El tercer método de diseño define las clases o tipos, que nos permite reutilizar definiciones de elementos. Esto se hace nombrando los elementos simpleTypes y complexTypes, y luego apunte a ellos a través del type atributo del elemento.
Aquí es el tercer diseño del archivo de esquema ("shiporder.xsd") :
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="stringtype">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="inttype">
<xs:restriction base="xs:positiveInteger"/>
</xs:simpleType>
<xs:simpleType name="dectype">
<xs:restriction base="xs:decimal"/>
</xs:simpleType>
<xs:simpleType name="orderidtype">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{6}"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="shiptotype">
<xs:sequence>
<xs:element name="name" type="stringtype"/>
<xs:element name="address" type="stringtype"/>
<xs:element name="city" type="stringtype"/>
<xs:element name="country" type="stringtype"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="itemtype">
<xs:sequence>
<xs:element name="title" type="stringtype"/>
<xs:element name="note" type="stringtype" minOccurs="0"/>
<xs:element name="quantity" type="inttype"/>
<xs:element name="price" type="dectype"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="shipordertype">
<xs:sequence>
<xs:element name="orderperson" type="stringtype"/>
<xs:element name="shipto" type="shiptotype"/>
<xs:element name="item" maxOccurs="unbounded" type="itemtype"/>
</xs:sequence>
<xs:attribute name="orderid" type="orderidtype" use="required"/>
</xs:complexType>
<xs:element name="shiporder" type="shipordertype"/>
</xs:schema>
El elemento de restricción indica que el tipo de datos se deriva de un tipo de datos de espacio de nombres W3C esquema XML. Por lo tanto, el siguiente fragmento significa que el valor del elemento o atributo debe ser un valor de cadena:
<xs:restriction base="xs:string">
El elemento de restricción se utiliza más a menudo para aplicar restricciones a los elementos. Mira las siguientes líneas del siguiente esquema:
<xs:simpleType name="orderidtype">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{6}"/>
</xs:restriction>
</xs:simpleType>
Esto indica que el valor del elemento o atributo debe ser una cadena, debe ser exactamente seis caracteres en una fila, y los caracteres debe ser un número del 0 al 9.