Validación e Tipos de Documentos
Introducción a Validación de Documentos.
A validación XML consiste na comprobación de que un documento XML está ben formado e se axusta a unha estructura previamente definida (esquema). Para que un documento XML esté ben formado debe seguir as regras básicas establecidas para o deseño de documentos XML. A validez dun documento XML require que, además de estar ben formado, a súa estructura se axuste á definición do documento establecida previamente mediante unha definición de tipo de documento.
Para a definición dos documentos utilízanse varias linguaxes de definición de estructuras de datos, sendo o máis empregado hoxe en día o DTD (Document Type Definition) convivindo con outras máis complexas como XML-Schema, Relax NG ou Schematron.
Definición de Tipos de Documentos
DTD
Unha Definición de Tipo de Documento é unha descripción da estructura e sintaxe dun documento XML ou SGML. A súa función básica é a descripción do formato dos datos de modo que se manteña a consistencia entre todos os documentos válidos que utilizan o mesmo DTD. O DTD pódese incluir dentro do arquivo do documento, pero normalmente se almacena nun ficheiro de texto separado, e indica a sintaxis a seguir por un documento XML como por exemplo XHTML.
Nun DTD se describe:
- Elementos
- Que etiquetas se permiten e que contido poden ter.
- Estructura
- Describe en que orde deber ir as etiquetas no documento.
- Anidamento
- Describe que etiquetas van dentro de outras.
Si declaramos o DTD dentro do ficheiro XML, debería estar dentro dunha definición DOCTYPE coa seguinte sintaxe:
<!DOCTYPE root-element [element-declarations]>
Por exemplo:
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
Si o DTD está declarado nun ficheiro externo, se pode declarar coa seguinte sintaxe:
<!DOCTYPE root-element SYSTEM "filename">
Por exemplo, o caso anterior quedaría como sigue:
- Ficheiro “nota.dtd”
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
- Ficheiro “nota.xml”
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
A sintaxe xeral da declaración DOCTYPE é a seguinte:
<!DOCTYPE [Raiz] [Dispoñibilidade] "[Rexistro]// [Organización]// [Tipo] [Etiqueta]// [Linguaxe]" "[URL]">
"//" se utiliza como separación entre os distintos campos.
- [Raíz]
- – Indica o nome da etiqueta raíz declarada no DTD. Por exemplo <html> en HTML.
- [Dispoñibilidade]
- – Indica si e un obxecto accesible públicamente (PUBLIC) ou un recurso do sistema (SYSTEM) como unha URL ou un ficheiro local.
- [Rexistro]
- – Pode ser “+” indicando que a organización que se indica a continuación forma parte da ISO, ou “-”, indicando que non. O IETF e W3C non forman parte da ISO e polo tanto utilizan “-”.
- [Organization]
- – E unha etiqueta única indicando a organización responsable da creación e mantemento do DTD.
- [Tipo]
- – E o tipo de obxecto que está a ser referenciado, no caso dos DTD, se especificará DTD.
- [Etiqueta]
- – E unha descripción pública única do DTD que está a ser referenciado.
- [Linguaxe]
- – E a linguaxe que se utilizará na creación do documento. Se debe especificar o código da linguaxe segun o estándar ISO 639 (dúas letras maiúsculas)
- [URL]
- – URL ao DTD ao que se está a facer referencia
Para a creación dun DTD distinguiremos entre:
- Elementos
- Son as etiquetas que formarán o documento XML.
- Atributos
- Proporcionan información extra sobre un elemento, no XML irán situados no interior da declaración de apertura da etiqueta.
- Entidades
- Definición de abreviaturas para referirse a caracteres de uso especial en XML, como por exemplo en XHTML.
- PCDATA
- E o texto que se atopa dentro dunha etiqueta XML. Este texto o examina o analizador XML en busca de entidades e novos elementos anidados.
- CDATA
- E o texto que se atopa dentro dunha etiqueta XML. Este texto NON será examinado en busca de novos elementos anidados e entidades.
As DTD teñen limitacións como a falta de definición de etiquetas locais a outros elementos, de modo que non se permite repetir etiquetas aínda que estean en ámbitos distintos (por exemplo, <delegado> dentro da etiqueta <clase> e <delegado> dentro da etiqueta <consello escolar>) forzando o uso de espacios de nomes. Tampouco é posible indicar con precisión os tipos de datos dos atributos dos elementos... etc. Para superar estas limitacións apareceron outras linguaxes de esquema como XML-Schema.
XML-Schema
Como xa comentamos, XML-Schema permite unha definición máis estricta dos documentos XML, permitíndonos indicar entre outras cousas a información permitida no mesmo. Un resumo útil para a elaboración de documentos XML-Schema pode ser o seguinte:
- Referencia a un XML-Schema nun documento XML
Os documentos XML referencian o seu Schema mediante atributos situados na etiqueta raíz do documento. Un exemplo sería o seguinte:
<?xml version="1.0"?>
<etiqueta_raiz xmlns="http://urldonososchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://urldonososchema nososchema.xsd">
....
</etiqueta_raiz>
Alternativamente, dun xeito máis simple:
<etiqueta_raiz xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="nososchema.xsd">
......
</etiqueta_raiz>
- Encabezado dun documento XML-Schema
A definición dun documento XML-Schema comenza cunha etiqueta schema, que pode levar diversos atributos (consultar manual). Un xeito de comenzar un documento XML-Schema sería o seguinte:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://urldonososchema"
xmlns="http://urldonososchema" elementFormDefault="qualified">
Alternativamente, dun xeito máis simple:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
...
</xs:schema>
- Definición de etiquetas (elements)
As etiquetas (chamadas elements en XML-Schema) poden ser simples ou complexas. As etiquetas simples son aquelas que únicamente teñen información como contido, e non conteñen nin outras etiquetas nin atributos (un atributo é unha característica da etiqueta que se indica dentro da propia etiqueta, por exemplo en <documento linguaxe=”galego”>, linguaxe sería un atributo da etiqueta documento, sendo polo tanto unha etiqueta complexa.
As etiquetas (elements) simples declaranse do seguinte xeito:
<xs:element name="xxx" type="yyy"/>
Donde name é o nome da etiqueta e type o seu tipo (o tipo de información que pode conter a etiqueta). XML-Schema dispón de varios tipos predefinidos que podes consultar no manual. Ás etiquetas simples se lles pode asignar un valor por defecto:
<xs:element name="xxx" type="yyy" default=”valor por defecto”/>
Ou un valor fixo:
<xs:element name="xxx" type="yyy" fixed=”valor fixo”/>
A definición de etiquetas complexas é similar a das etiquetas simples, pero no interior da súa definición se indicarán os distintos elementos que a compoñen:
<xs:element name=”etiqueta”>
<xs:complexType>
Definición das etiquetas e atributos que poden ir na etiqueta
</xs:complexType>
</xs:element>
XML-Schema dispon de varios tipos de datos, sendo os máis habituais os seguintes: xs:string, xs:decimal, xs:integer, xs:boolean, xs:date, xs:time
- Definición de atributos (attributes)
Como xa comentamos, os atributos son características dunha etiqueta que se indican dentro da propia etiqueta. A súa definición é como sigue:
<xs:attribute name="xxx" type="yyy"/>
Do mesmo xeito que as etiquetas simples é posible indicar un valor fixo, ou una valor por defecto, pero tamén podemos indicar si queremos que sexa obrigatorio especificar o atributo mediante a seguinte declaración:
<xs:attribute name="lang" type="xs:string" use="required"/>
- Restriccións de valores
En XML-Schema podemos restrinxir a información que se pode especificar no interior de unha etiqueta ou dun atributo mediante os tipos de datos, pero aínda se pode restrinxir máis o conxunto de valores permitidos especificando restriccións sobre cada tipo:
<xs:element name=”elemento”>
<xs:simpleType>
<xs:restriction base=”xs:tipo_base”>
Definición da restricción
</xs:restriction>
</xs:simpleType>
</xs:element>
A definición das restriccións pode ser de varios tipos, como valores máximos e/ou mínimos, enumeracións, patróns de validación (pattern), lonxitude.... etc. (consultar manual). Vexamos un par de exemplos:
1.- o contido da etiqueta dni ten que consistir en 7 díxitos numéricos seguidos dunha letra maiúscula.
<xs:element name=”dni”>
<xs:simpleType>
<xs:restriction base=”xs:string”>
<xs:pattern value=”[0-9][0-9][0-9][0-9][0-9][0-9][0-9][A-Z]”/>
</xs:restriction>
</xs:simpleType>
</xs:element>
2.- o contido da etiqueta texto ten que ter como mínimo 8 letras, e como máximo 30
<xs:element name=”texto”>
<xs:simpleType>
<xs:restriction base=”xs:string”>
<xs:minLength value="8"/>
<xs:maxLength value=”30”/>
</xs:restriction>
</xs:simpleType>
</xs:element>
Outros tipos de restriccións que se poden especificar son:
- 'enumeration - Define unha lista de valores aceptables:
<xs:enumeration value="Audi"/>
<xs:enumeration value="Golf"/>
<xs:enumeration value="BMW"/>
- fractionDigits - Número máximo de posicións decimais a utilizar. (a base debe ser xs:decimal)
- length - Número exacto de caracteres ou de elementos de lista
- maxExclusive - Valor máximo dun contido numérico (non incluído)
- maxInclusive - Valor máximo dun contido numérico (incluído)
- maxLength - Lonxitude máxima dun contido
- minExclusive - Valor mínimo dun contido numérico (non incluido)
- minInclusive - Valor mínimo dun contido numérico (incluido)
- minLength - O contido debe ter máis que o número de caracteres especificado
- pattern - Especifica un patron que debe cumplir o contido
- totalDigits - Número máximo de díxitos permitido
- whiteSpace - Uso dos espacios en blanco no documento. Pode ser “preserve”, “replace” ou “collapse”
Definición do contido das etiquetas complexas Unha etiqueta complexa pode conter: nada (únicamente ten atributos, non contido) Neste caso nos limitamos a declarar os atributos dentro da declaración de complexType: <product prodid='9'/> <xs:element name="product"> <xs:complexType> <xs:attribute name="prodid" type="xs:positiveInteger"/> </xs:complexType> </xs:element> so outros elementos Podemos definir os elementos como: 1. SEQUENCE: Unha secuencia: Os elementos declarados deben aparecer no orde indicado: <person><firstname>Manuel</firstname><lastname>Pérez</lastname></person> <xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> 2. CHOICE: Unha etiqueta a elexir entre un grupo (choice) <contacto><email>correo@dominio.es</email></contacto> <xs:element name="contacto"> <xs:complexType> <xs:choice> <xs:element name="telefono" type="xs:string"/> <xs:element name="email" type="xs:string"/> </xs:choice> </xs:complexType> </xs:element> 3. ALL: Varias etiquetas que poden aparecer en calqueira orden <person><lastname>Pérez</lastname><firstname>Manuel</firstname></person> <xs:element name="person"> <xs:complexType> <xs:all> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> </xs:all> </xs:complexType> </xs:element> so texto (e atributos) etiquetas con atributos e so con texto no seu interior. Se define un contido simple dentro do contido complexo, extendendo un tipo ou poñendo unha restricción: <shoesize country="france">35</shoesize> <xs:element name="shoesize"> <xs:complexType> <xs:simpleContent> <xs:extension base="xs:integer"> <xs:attribute name="country" type="xs:string" /> </xs:extension> </xs:simpleContent> </xs:complexType> </xs:element>
contido mixto (outros elementos e texto) Se realiza poñendo mixed=”true” na definición do tipo complexo. Se queremos que unha etiqueta poda aparecer máis dunha vez, podemos especificar o número máximo con maxOccurs na definición da mesma. Do mesmo xeito podemos facer que apareza un número mínimo de veces con minOccurs, pudendo indicar 0 si queremos que poda non aparecer.
Relax NG. RELAX NG é unha linguaxe de definición de esquemas para XML, basado en XML. Consideremos un documento XML que representa información sobre libros dunha biblioteca: <biblioteca> <libro> <titulo>20000 Leguas de viaxe submarina</titulo> <autor>Julio Verne</autor> </libro> <libro> <titulo>Festín de Corvos</titulo> <autor>R.R. Martin</autor> </libro> </biblioteca> A definición do esquema DTD seria: <!DOCTYPE biblioteca [ <!ELEMENT biblioteca (libro*)> <!ELEMENT libro (titulo, autor)> <!ELEMENT titulo (#PCDATA)> <!ELEMENT autor (#PCDATA)> ]> E o Relax NG sería algo así: <element name="biblioteca" xmlns="http://relaxng.org/ns/structure/1.0">
<zeroOrMore> <element name="libro"> <element name="titulo"> <text/> </element> <element name="autor"> <text/> </element> </element> </zeroOrMore>
</element> Podemos observar etiquetas como <ZeroOrMore> que indican a cardinalidade do contido, pudendo utilizarse por exemplo <OneOrMore>. Examinaremos as etiquetas máis importantes: <element name="nome"> Permite a definición de etiquetas que poden estar presentes no documento XML <choice> Permite a elección entre dous conxuntos de etiquetas que poden estar agrupados co tag <group>, sería o equivalente ao paréntesis no DTD, e choice faría a función de |. Esta etiqueta utilízase tanto nos elementos como nos atributos, e se poden facer eleccións entre elementos e atributos. <attribute name="nome"> Vai dentro dun <element> e permite definir atributos do elemento <optional> Os elementos e atributos definidos dentro dun tag <optional> serán opcionais <text/> Indica que o contido do elemento ou atributo é texto. É o valor por defecto para os atributos. Os elementos teñen que ter definido un tipo de contido obrigatoriamente. <empty/> Indica que un elemento non ten contido. <grammar> Grammar permite definir un esquema Relax NG dun xeito "modular", o que simplifica a definición, comprensión e mantemento do mesmo. A etiqueta <grammar> consta dunha etiqueta <start> e de cero ou máis etiquetas <define name='nome'>. Na etiqueta <start> se realizará a definición da etiqueta raíz, cos elementos do segundo nivel facendo referencia á sección <define> onde se atopa o esquema a aplicar, mediante un tag <ref name='nome'>, permitíndose referencias recursivas. Esta etiqueta permite definir o tipo de datos da información. O atributo datatypeLibrary contén unha url identificando a librería de tipos de datos a utilizar, sendo a de W3C (W3C XML Schema Datatypes) http://www.w3.org/2001/XMLSchema-datatypes, que define tipos como integer ou double. O atributo datatypeLibrary pode indicarse no tag ou no tag <element> pai. Os poden ter parámetros que restrinxen o rango de valores permitidos. Estes parámetros se indican cun elemento fillo <param name='restricción'>, donde restricción pode ser por exemplo maxLength. O tag <define> pode levar un atributo combine que pode ter dous valores distintos: choice - Indica que no documento XML é posible elexir entre todas as definicións co mesmo nome. interleave - Indica que se poden utilizar calqueira dos elementos definidos co mesmo nome, e en calqueira orde. <value> Permite indicar un valor fixo para un elemento ou atributo. <list> Permite que un elemento ou atributo conteña unha lista de datos. <interleave> Permite que os elementos definidos podan especificarse en calqueira orde <externalRef href='url'> Permite facer referencia a un esquema RelaxNG definido en outro ficheiro. Utilízase na separación modular de esquemas mediante o tag <grammar>.