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 en un ficheiro de texto separado e indica a sintaxis a seguir por un documento XML como pode ser por exemplo XHTML. Un DTD 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: a) 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>
b) 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> 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 “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>.