DTD (Tercera parte)

DECLARACIÓN DE ATRIBUTOS

La declaración de atributos es similar en cierto sentido a la declaración de elementos. En vez de declarar modelos de contenido válido para los elementos, declaramos atributos para cada elemento. Estas listas son llamadas ATTLIST. Por ejemplo:

<!ELEMENT contactos (contacto*)> <!ATTLIST contactos source CDATA #IMPLIED>

En el ejemplo anterior hemos declarado los atributos del elemento "contactos", que define sus atributos válidos. Una declaración ATTLIST, consiste en tres partes básicas: La palabra reservada ATTLIST, un nombre de elemento asociado, y la lista de atributos declarados.

Las dos primeras partes son perfectamente comprensibles sin más explicaciones: <!ATTLIST contactos .... >

La tercera parte es la que centra nuestra atención: source CDATA #IMPLIED. Vamos a analizarla.

source es el nombre del atributo. CDATA indica que el atributo puede contener elementos de tipo carácter. Finalmente, #IMPLIED indica que el atributo no tiene un valor por defecto y que no tiene necesariamente que estar presente en todo elemento "contactos".

LOS NOMBRES DE LOS ATRIBUTOS

Las reglas para los nombres de los atributos son las mismas que para los nombres de los elementos. También es importante recordar que no se pueden duplicar nombres de atributo en una misma lista. En caso de necesitar usar en el documento prefijos para un namespace, es preciso declararlo en la ATTLIST.

LOS TIPOS DE LOS ATRIBUTOS

Los DTD permiten definir de qué naturaleza son los datos que aparecen en un atributo, a lo que se llama "tipo de datos". Los diferentes tipos de datos de los atributos son:

  • "CDATA": Indica que el atributo contiene caracteres. Dichos caracteres no serán analizados sintácticamente.
  • "ID": Indica que el valor del atributo identifica que manera única al elemento que lo contiene. Ya has podido ver esto con CSS y XHTML. Todo atributo ID debe respetar las normas de nombres XML. El valor de un ID debe ser único en todo el documento XML. Sólo puede haber un atributo ID por elemento. Un atributo ID siempre debe tener en la declaración el valor #IMPLIED o #REQUIRED (después explicaremos esto). Por ejemplo:
    <!ATTLIST contact persona ID #REQUIRED>
    Esta definición define como válido el siguiente elemento: <contacto persona="José_Pérez"> Recordemos que los nombres XML no aceptan espacios en blanco.
  • "IDREF": Indica que el valor del atributo es una referencia a un ID de un elemento únivocamente identificable. De este modo se pueden hacer referencias cruzadas entre elementos. IDREF debe respetar las normas de nombre de XML. También debe coincidir con el valor de algún ID del documento. Por ejemplo:
  • <!ATTLIST conocidos contacto IDREF #REQUIRED>
    Esta definición define como válido el siguiente elemento:
    <conocidos contacto="José_Pérez">
  • "IDREFS": Indica que el valor del atributo es una lista de IDREF separadas por espacio. Usamos este tipo cuando tenemos que referirnos a varios contactos, siguiendo el ejemplo anterior. En tal caso, para la definición siguiente:
  • <!ATTLIST conocidos contactos IDREFS #REQUIRED>
    El siguiente elemento sería válido:
    <conocidos contacto="José_Pérez Antonio_García">
  • "ENTITY": Indica que el valor del atributo es una referencia a una entidad externa sin analizar sintácticamente. La entidad sin analizar sintáctiamente puede ser un fichero de imagen, u otros recursos externos como un MP3 u otros ficheros binarios. De este modo, en vez de incluir el fichero en el documento, hacemos referencia al recurso externo. Los atributos ENTITY deben siempre referirse a una "ENTIDAD" definida previamente en el DTD. Su valor debe respetar las normas de nombres de XML. Por ejemplo, para la siguiente definición:
    <!ATTLIST contacto foto ENTITY #IMPLIED>
    Podríamos incluir el siguiente elemento en el documento:
    <contacto foto="Foto_José_Pérez">
    Donde el atributo foto se refiere a una entidad definida en el documento, llamada "Foto_José_Pérez". Aun no hemos visto las entidades, así que no te preocupes si no te queda del todo claro.
  • "ENTITIES": Indica que el valor del atributo es una lista de ENTITY's separados por espacio. Si fuese preciso indicar más de una entidad, lo haríamos del siguiente modo. Para la declaración siguiente:
  • <!ATTLIST contacto fotos ENTITIES #IMPLIED>
    Podríamos incluir el siguiente elemento en el documento:
    <contacto fotos="Foto_José_Pérez Foto_Antonio_García">

    NOTA: Los valores pueden estar separados por más de un espacio, e incluso un retorno de carro.

  • "NMTOKEN": Es un nombre XML válido.
    <!ATTLIST contacto etiqueta NMTOKEN #IMPLIED>
    El siguiente elemento sería válido:
    <contacto etiqueta="jefe">
    Los atributos NMTOKEN pueden empezar por un número o por cualquier carácter, de modo que es similar en esto a CDATA. Sin embargo, es preciso que un NMTOKEN respete las normas de nombres válidos XML (lo que significa que solo puede contener dígitos, letras y guiones bajos; no permite espacios en blanco).
  • "NMTOKENS": Indica que el valor del atributo es una lista de valores NMTOKEN separados por espacio. Del mismo modo que ocurría con IDREFS y ENTITIES, podemos declarar varios tokens para un atributo NMTOKENS. Por ejemplo:
    <!ATTLIST contacto etiqueta NMTOKENS #IMPLIED>
    El siguiente elemento sería válido:
    <contacto etiqueta="supervisor encargado">
    jenifer rush
  • "Lista enumerada": A demás de usar los tipos por defecto, se pueden declara una lista de posibles valores de atributo. Usaremos una lista enumerada cuando necesitemos reglas más restrictivas para un cierto tipo de datos. Por ejemplo, supongamos que queremos establecer el tipo de vehículo para un elemento llamado "vehículo":
  • <!ATTLIST vehículo tipo (bicicleta | scooter | motocicleta | turismo | berlina | monovolumen | furgoneta | camión) #IMPLIED>
    Aunque esta lista sea incompleta, ilustra la idea. El siguiente elemento sería válido:
    <vehículo tipo="monovolumen">

DECLARACIÓN DEL VALOR DEL ATRIBUTO

A lo largo de la sección anterior, aparece constantemente la palabre #IMPLIED y #REQUIRED. Estos valores sirven para indicar de qué forma aparece el atributo en el elemento. La recomendación XML permite que un atributo...

A) Tenga un valor por defecto,

B) Tenga un valor fijo,

C) Siempre tenga algún valor especificado o

D) Que sea opcional.

VALORES POR DEFECTO DE UN ATRIBUTO

Observa la siguiente declaración:

<!ATTLIST vehículo tipo (bicicleta | scooter | motocicleta | turismo | berlina | monovolumen | furgoneta | camión) "turismo">

Esto significa que si no se especifica, el valor por defecto será "turismo". Cuando el analizador sintáctico encuentre el elemento <vehículo>, sin el atributo tipo, asumirá que su valor es "turismo". Obviamente, este valor debe estar entre los posibles de acuerdo con el tipo del atributo.

NOTA: No es posible indicar un valor por defecto para un atributo ID.

VALORES FIJOS DE UN ATRIBUTO

Observa la siguiente declaración:

<!ATTLIST contactos version CDATA #FIXED "1.0">

Si utilizamos el atributo "versión" en el elemento "contactos", entonces deberá tener el valor "1.0". Esta estrategia puede tener sentido para indicar un número de versión de un tipo de elemento.

VALORES REQUERIDOS DE UN ATRIBUTO

Si un atributo es definido como #REQUIRED, es obligatorio que el elemento incluya un valor para el atributo. Si por ejemplo para el caso anterior del elemento vehículo, necesitamos que se indique el valor del atributo, entonces la declaración sería como la siguiente:

<!ATTLIST vehículo tipo (bicicleta | scooter | motocicleta | turismo | berlina | monovolumen | furgoneta | camión) #REQUIRED>

En tal caso, el elemento <vehículo> sería incorrecto puesto que no incluye el atributo tipo especificado.

VALORES OPCIONALES DE UN ATRIBUTO

En la mayoría de los casos, el atributo declarado no será obligatorio, y ni tan siquiera tendrá un valor por defecto. Estos atributos son los #IMPLIED. Un atributo con un tipo de valor #IMPLIED, será revisado por el analizador sintáctico, comprobando sencillamente que en el caso de que esté presente en el elemento, cumple lo relativo al tipo de dato. Observa el siguiente ejemplo:

<!ATTLIST vehículo tipo (bicicleta | scooter | motocicleta | turismo | berlina | monovolumen | furgoneta | camión) #IMPLIED>

DECLARAR MÁS DE UN ATRIBUTO

Se pueden declarar varios atributos en una sola declaración. Observa el siguiente ejemplo:

<!ATTLIST contactos versión CDATA #FIXED "1.0" source CDATA #IMPLIED>

En este caso, el atributo versión tiene un valor fijo a "1.0", y el atributo source es de tipo CDATA y es opcional.

Las siguientes declaraciones son equivalentes:

<!ATTLIST contactos versión CDATA #FIXED "1.0" source CDATA #IMPLIED> ----- <!ATTLIST contactos versión CDATA #FIXED "1.0"> <!ATTLIST contactos source CDATA #IMPLIED>

Observa que en la última declaración se emplea más de una ATTLIST. Es posible utilizar tantas ATTLIST para un solo elemento como sea necesario.

Práctica 4. Para el siguiente documento XML, crea un DTD que defina su estructura. Una vez que lo termines, valida el documento XML. Especifica los atributos siguiendo las siguientes instruccciones:

  • Para el elemento "alumnos":
    • atributo "curso" de tipo CDATA, obligatorio.
    • atributo "centro" de tipo CDATA, obligatorio.
  • Para el elemento "alumno":
    • atributo "versión" de tipo CDATA, con valor fijo a "0.0".
    • atributo "persona" de tipo ID obligatorio.
    • atributo "indicador" de tipo NMTOKEN con valor por defecto "nuevo".
  • Para el elemento "teléfono":
    • atributo "tipo" de tipo enumerado, con los valores posibles "fijo", "móvil", obligatorio.
  • Para el elemento "pareja":
    • atributo alumnos, de tipo IDREFS, hace referencia a los alumnos con que se sienta en clase.

NOTA: El elemento pareja es vacío.

<alumnos curso="1ASIR" centro="IES Guadalpín"> <alumno persona="José_Pérez" indicador="repetidor"> <persona> <nombre>José</nombre> <apellido1>Pérez</apellido1> <apellido2>Pérez</apellido2> </persona> <localización> <dirección>Lamentos, Mordor, España</dirección> <dirección>Gotham, Teruel, España</dirección> </localización> <teléfono tipo="fijo">123234435</teléfono> <teléfono tipo="móvil">645234123</teléfono> <pareja alumnos="Pedro_García Antonio_Pérez"/> <comentario>Es muy constante</comentario> </alumno> <alumno persona="Pedro_García" indicador="nuevo"> <persona> <nombre>Pedro</nombre> <apellido1>García</apellido1> <apellido2>Jiménez</apellido2> </persona> <localización> <dirección>Lamentos, Mordor, España</dirección> <dirección>Ciudadela, Gondor, España</dirección> </localización> <teléfono tipo="fijo">123234665</teléfono> <teléfono tipo="móvil">6452566723</teléfono> <pareja alumnos="José_Pérez Antonio_Pérez"/> <comentario>Se copia</comentario> </alumno> <alumno persona="Antonio_Pérez" indicador="repetidor"> <persona> <nombre>Antonio</nombre> <apellido1>Pérez</apellido1> <apellido2>Rodríguez</apellido2> </persona> <localización> <dirección>Villa Abajo, Mordor, España</dirección> <dirección>Gotham, Teruel, España</dirección> </localización> <teléfono tipo="fijo">234234435</teléfono> <teléfono tipo="móvil">5345234123</teléfono> <pareja alumnos="José_Pérez Pedro_García"/> <comentario>No hace nada</comentario> </alumno> </alumnos>

Entrega la actividad con el nombre Act4-dtd.dtd

ENTIDADES

Anteriormente, vimos algunas entidades que incorpora por defecto XML, como por ejempo &amp;. Estas entidades se usan para escribir ciertos caracteres problemáticos en determinados contextos. Pero las entidades no se limitan a simples referencias a caracteres en los documentos XML. En realidad con las entidades nos podemos referir a secciones o sustituciones de texto, marcas específicas XML e incluso ficheros externos. Podemos distinguir entre cuatro tipos principales de entidades:

  • A) Entidades por defecto,
  • B) Entidades de carácter,
  • C) Entidades generales y
  • D) Entidades paramétricas.

ENTIDADES POR DEFECTO

Ya conocemos las 5 entidades por defecto: &amp; &lt; &gt; &quot; y &apos;

Estas entidades están recogidas en la recomendación de XML, y todos los analizadores sintácticos deben soportarlos.

Las entidades por defecto se pueden usar en cualquier sitio donde se usaría texto en el documento XML. Por ejemplo, puedes usar una entidad por defecto en el contenido de un elemento, en el valor de un atributo o incluso en un valor por defecto para un atributo en una DTD. Sin embargo, no se puede usar una entidad por defecto en el nombre de un elemento o de un atributo.

ENTIDADES DE CARÁCTER

Se parecen mucho a las entidades por defecto anteriormente reseñadas. Se pueden usar en el documento XML dentro del contenido de un elemento o un atributo. Se usan para caracteres de difícil escritura, o caracteres no ASCII. Por ejemplo, la entidad &#169; hace referencia al carácter ©. Se trata del carácter &, seguido de # para indicar que es una entidad de cáracter, y el valor numérico UNICODE del carácter. También podemos usar el valor numérico en hexadecimal. Por ejemplo ©. En la página http://unicode.coeurlumiere.com/ podemos encontrar todos los caracteres Unicode.

ENTIDADES GENERALES

Podemos crear una entidad que haga referencia a un texto que reusamos constantemente durante el documento XML. Por ejemplo, si utilizamos constantemente la cadena de texto "{3F2504E0-4F89-11D3-9A0C-0305E82C3301}", podemos definir una entidad que represente esta cadena, y así evitamos tener que escribirla una y otra vez; y de paso evitamos equivocarnos al escribirla. Observa el siguiente ejemplo:

<!ENTITY miGuid "{3F2504E0-4F89-11D3-9A0C-0305E82C3301}">

Esta entidad es declarada en la DTD. Más adelante, en el documento XML, podemos escribir los siguiente:

<recurso>&miGuid;</recurso>

De modo que el analizador sintáctico sustituirá la cadena anterior por <recurso>{3F2504E0-4F89-11D3-9A0C-0305E82C3301}</recurso>.

Si queremos, podemos incluir en la entidad cualquier cosa, incluidos elementos. Observa el siguiente ejemplo.

<!ENTITY localización-vacía "<localización><dirección></dirección></localización>">

La única condición a cumplir es que si se incluyen elementos, atributos, etc., debe tratarse de un texto bien formado. Es decir, que la siguiente entidad sería ilegal, por ejemplo:

<!ENTITY inicio-dirección "<dirección>">

Las entidades declaradas hasta el momento son internas, ya que están explícitamente declaradas en el DTD. Sin embargo también podemos hacer referencia a entidades externas. Observa el siguiente ejemplo:

<!ENTITY José_Pérez SYSTEM "josep.txt">

Si el analizador sintáctico tiene capacidad de validación, además de analizar el fichero, puede utilizar el contenido cuando es referenciado. Si no tiene capacidad de validación, puede que sí o puede que no analice el fichero externo.

Práctica 5. Tomando el ejemplo anterior, crea tres entidades, llamadas "nada", "constante" y "copia".

  • "constante" tendrá el contenido siguiente: <comentario>Es muy constante</comentario>
  • "vago" tendrá el contenido siguiente: <comentario>No hace nada</comentario>
  • "copia" tendrá el comentario siguiente: <comentario>Se copia</comentario>

Una vez declaradas las entidades, empléalas en el documento XML. Una vez terminado, valida el código.

Entrega la actividad con el nombre Act5-dtd.dtd

Si queremos usar una entidad general desde un atributo de tipo NMTOKEN, debemos añadir el tipo de entidad de que se trata. Por ejemplo, si quiero añadir una entidad que hace referencia a un archivo de texto llamado "jose.txt, en el dtd añadiría la siguiente entidad:

<!ATTLIST contacto fotos ENTITY #IMPLIED> [...] <!ENTITY companyLogo SYSTEM "logo.jpg" NDATA jpeg> <!NOTATION jpeg SYSTEM "image/jpeg">

Mediante la declaración NOTATION definimos el MIME-TYPE del archivo. Posteriormente, desde el documento XML puede hacer referencia a la entidad companyLogo. Por ejemplo:

[...] <contacto fotos="companyLogo">...</contacto> [..]

ENTIDADES PARAMÉTRICAS

Las entidades paramétricas son parecidas a las entidades generales, pero con la salvedad de que solo se pueden usar en las declaraciones de las DTD. Por ejemplo:

<!ENTITY % ContentTypes "CDATA">

El símbolo % deja claro que se trata de una entidad paramétrica. Además es una entidad paramétrica interna, puesto que está explícitamente definida en el DTD. Los espacios entre %, ENTITY y el nombre del parámetro son obligatorios.

También podemos hacer referencia a un recurso externo. Por ejemplo:

<!ENTITY % DeclaracionesDeNombre SYSTEM "nombres.dtd">

De este modo, podemos importar trozos de DTD externas, incluyendo todo tipo de entidades en ellas. Esta técnica permite modularizar la construcción de las DTD, lo que es muy ventajoso para las tareas de mantenimiento y trabajo en equipo.

Para hacer referencia a una entidad paramétrica, usamos el nombre de la entidad, precedida de %. Por ejemplo, para el caso anterior:

%DeclaracionesDeNombre;

Observa este otro ejemplo:

<!ENTITY % dos_ruedas "bicicleta | scooter | motocicleta"> <!ENTITY % cuatro_ruedas "turismo | berlina | monovolumen | furgoneta | camión"> <!ATTLIST vehículo tipo (%dos_ruedas; | %cuatro_ruedas) "turismo">

Práctica 6. Dispones del siguiente DTD que define un lenguaje para el catálogo de productos de un almacén:

<!ELEMENT almacen (item)*> <!ELEMENT item (nombre, descripcion, precio, relacionados*, ubicacion, existencias)> <!ELEMENT nombre (#PCDATA)> <!ELEMENT descripcion (#PCDATA)> <!ELEMENT precio (#PCDATA)> <!ELEMENT relacionados (item_relacionado)*> <!ELEMENT item_relacionado (#PCDATA)> <!ELEMENT ubicacion (pasillo,estanteria)> <!ELEMENT pasillo EMPTY> <!ELEMENT estanteria EMPTY> <!ELEMENT existencias EMPTY> <!ATTLIST item id ID #REQUIRED> <!ENTITY % monedas_estandar "euro | dolar"> <!ATTLIST precio moneda (%monedas_estandar;) "euro"> <!ATTLIST item_relacionado id IDREF #REQUIRED> <!ATTLIST pasillo numero CDATA #REQUIRED> <!ATTLIST estanteria numero CDATA #REQUIRED> <!ATTLIST existencias cantidad CDATA #REQUIRED>

Escribe un documento XML que siga la definición del DTD para especificar la siguiente información:

  • Producto 1:
    • Nombre: Portátil Lenovo Essential B50-30
    • Id: Len-B50-30
    • Descripción: Portátil de gama baja, con prestaciones interesantes para el usuario no profesional.
    • Precio: 287 euros
    • Otros productos relacionados: Len-G50-70
    • Ubicado en: pasillo 15, estantería 3
    • Stock: 5 unidades
  • Producto 2:
    • Nombre: Portátil Lenovo G50-70
    • Id: Len-G50-70
    • Descripción: Portátil de gama media, con procesador Intel i7, 16GB de RAM DDR3 y 1TB de disco destinado al usuario profesional.
    • Precio: 916 euros
    • Otros productos relacionados: Len-B50-30
    • Ubicado en: pasillo 15, estantería 4
    • Stock: 2 unidades
  • Producto 3:
    • Nombre: Disco Duro Externo 1TB Toshiba Canvio Basics 2.5
    • Id: HD-Tosh-Canvio-25
    • Descripción: Serial ATA III, USB 3.0 de 1GB.
    • Precio: 60,40 euros
    • Otros productos relacionados:
    • Ubicado en: pasillo 7, estantería 2
    • Stock: 10 unidades

Una vez que escribas el documento XML, valídalo contra el DTD proporcionado.

Guarda el documento XML con el nombra Act6-dtd.xml

Saludos.