domingo, 25 de enero de 2015

XML Schemas y Xpath (Parte I)


Los schemas nos permiten la validación de un documento XML respecto a una normativa que nosotros mismos fijaremos. Así pues, podremos establecer que un documento XML deberá tener una serie de elementos mínimos, unos máximos, con unos atributos determinados, o en un orden determinado.

Un documento XSD (el tipo de extensión empleado por los archivos XML Schemas) comenzará por una estructura como la siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"                                         elementFormDefault="qualified">
    <xs:element name="root">
           <xs:complexType>
           </xs:complexType>
    </xs:element>
</xs:schema>

Podemos diferenciar, un primer elemento (root) el cual contendrá el resto de elementos. Esto quiere decir, que nuestro documento XML deberá poseer un primer elemento padre llamado root para validar. A este documento lo llamaremos midocumento.xsd.

El documento que se validará tendrá una estructura como la que se muestra a continuación:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="midocumento.xsd">
            (Contenido)
</root>

Como puede apreciarse, el documento XSD es enlazado en el propio elemento raíz mediante el atributo:

xsi:noNamespaceSchemaLocation="midocumento.xsd"

En el ejemplo anterior, el elemento “root” era de tipo complejo (ya que, como puede verse, posee dentro un “ComplexType”). No obstante, también existen los elementos simples. Las diferencias entre estos son:

Elementos simples:
     Los elementos simples sólo pueden contener texto.
     Por consiguiente, no podrá contener atributos ni otros elementos.

Elementos complejos:
     Pueden no tener contenido.
     Pueden contener otros elementos.
     Pueden contener solo texto.
     Pueden contener tanto elementos como texto.

Un ejemplo de elemento simple podría ser el siguiente:

              <xs:element name="nombre">
                    <xs:simpleType>                   
                    </xs:simpleType>
                </xs:element>

Además, los elementos simples (al igual que los complejos), permiten limitar el tipo de contenido que pueden tener. Por ejemplo, aquí se limita la longitud máxima del contenido:

               <xs:element name="nombre">
                    <xs:simpleType>
                      <xs:restriction base="xs:string">
                          <xs:maxLength value="20"/>               
                      </xs:restriction>

                    </xs:simpleType>
                </xs:element>


En este otro ejemplo, se aplica una regla de expresiones regulares:

              <xs:element name="dni">
                    <xs:simpleType>
                            <xs:restriction base="xs:string">
                                <xs:pattern value="([0-9]){8}|([0-9]){8}[A-Z]"/>
                            </xs:restriction>  
                  
                    </xs:simpleType>
                </xs:element>



Un ejemplo de un elemento complejo (definido anónimamente) sería:

<xs:element name="concierto">
       <xs:complexType>
                <xs:sequence></xs:sequence>
       </xs:complexType>
</xs:element>

Los elementos complejos permiten además, contener cadenas de texto entre sus elementos. Para ello ello, debe añadirse el atributo mixed:

<xs:element name="concierto">
       <xs:complexType mixed="true">
                <xs:sequence></xs:sequence>
       </xs:complexType>
</xs:element>

Los elementos complejos, pueden establecerse de dos formas: anónimamente o definiéndolos.

La forma anónima consiste en definir las propiedades y subelementos del elemento dentro del mismo. Por ejemplo:

<xs:element name="concierto">
       <xs:complexType>
                <xs:sequence></xs:sequence>
       </xs:complexType>
</xs:element>

La forma definida permite la reutilización de las reglas, como puede verse aquí:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="root">
        <xs:complexType>
            <xs:all>
                <xs:element name="concierto" type="evento" />
            </xs:all>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="evento">
        <xs:sequence></xs:sequence>
    </xs:complexType>
</xs:schema>

Es necesario remarcar, que los ComplexType definidos, deben encontrarse como elementos hijo del xs:schema.

Los ComplexType definidos de esta forma, pueden a su vez ser heredados de otros, como puede verse en el siguiente ejemplo:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="root">
        <xs:complexType>
            <xs:all><!--Mejor <xs:sequence maxOccurs="unbounded"> para agregar a varios -->
                <xs:element name="animal" type="animal"/>
                <xs:element name="gato" type="mamifero"/>
            </xs:all>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="animal">
        <xs:sequence>
            <xs:element name="nombre"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="mamifero">
        <xs:complexContent>
            <xs:extension base="animal">
                <xs:sequence>
                    <xs:element name="patas" type="xs:integer"/>
                    <xs:element name="ojos" type="xs:string"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
</xs:schema>

Los subelementos de un ContextType, pueden establecerse de 3 formas:
     all: Los elementos hijos pueden aparecer en cualquier orden.
     sequence: Los elementos hijos deben aparecer en el orden en que fueron definidos.
     choice: Debe aparecer un único elemento de los hijos.

Por defecto, los 3 únicamente permiten la definición de un hijo como máximo (u obligan la aparición de uno de ellos). No obstante, es posible cambiar este comportamiento mediante atributos:
     minOccurs: Apariciones mínimas del hijo. Puede ser 0.
     maxOccurs: Apariciones máximas del hijo. Úsese unbounded para no definir límite.

Por ejemplo, el siguiente documento mezcla las 3 formas:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="multimedia">
        <xs:complexType>
            <xs:all minOccurs="0">
                <xs:element name="pelicula" maxOccurs="
unbounded"  type="producto"/>
                <xs:element name="album" maxOccurs="
unbounded" type="producto"/>
                <xs:element name="revista" maxOccurs="
unbounded" type="producto" />
            </xs:all>
        </xs:complexType>
    </xs:element>
    <xs:complexType name="producto">
        <xs:sequence>
            <xs:element name="nombre" />
            <xs:element name="fecha" type="xs:date"></xs:element>
            <xs:choice>
                <xs:element name="nuevo"></xs:element>
                <xs:element name="usado"></xs:element>
            </xs:choice>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

No hay comentarios:

Publicar un comentario

¡Danos tu opinión!