Definición de los elementos
El XML no tiene elementos predefinidos. Cuando nos ponemos a escribir un documento XML,
no disponemos del H1, A o del IMG del HTML. Podemos utilizar nuestros propios elementos,
los cuales se definen en la DTD.
Esto lo realizamos mediante la declaración ELEMENT cuya sintaxis es la siguiente:
<!ELEMENT nombre_elemento (especificacion del contenido)>
Especificación del contenido
En esta parte de la declaración indicamos cúal va a ser el contenido de ese elemento. Como ya hemos visto en capítulos anteriores tenemos cuatro posibilidades:
- Que no tenga contenido.
- Que esté formado sólo por texto.
- Que esté formado únicamente por elementos.
- Que tenga un contenido mixto de texto y elementos.
Sin contenido
Esto se determina colocando la palabra clave EMPTY en la declaración del contenido. Son elementos que no tienen contenido y su valor suele estar determinado por los atributos. Es el caso de los elementos IMG, HR, BR, etc., del HTML.
Si a nuestro ejemplo de miniHTML queremos añadirle la posibilidad de trabajar con imágenes, como un elemento sin contenido cuyas propiedades especificaremos en los atributos, y que éstas puedan aparecer en cualquier lugar del documento, tendremos que añadir las siguientes declaraciones:
<!ELEMENT mihtml (c1 | parrafo | imagen)*>
....
<!ELEMENT imagen EMPTY>
Luego en el XML lo tendremos que escribir de la siguiente manera:
<imagen ...atributos... />
Contenido formado sólo por texto
Esto lo conseguimos colocando la palabra clave #PCDATA en la espeficicación del contenido. De esta manera estamos indicando que dentro de ese elemento no puede haber ningún otro elemento y que, por tanto, sólo nos encontraremos texto. En nuestro ejemplo es el caso del elemento negrita.
<!ELEMENT negrita (#PCDATA)>
Este elemento en XML se escribirá:
....<negrita>texto</negrita>.....
Contenido formado sólo por elementos
En este caso en la especificación del contenido sólo debemos indicar los nombres (identificadores genéricos) de otros elementos. Posiblemente éstos estén relacionados mediante los indicadores de aparición y conectores de grupo que explicamos más adelante.
En nuestro ejemplo es el caso del elemento mihtml en cuya declaración indicamos que estará formado por los elementos: c1, para e imagen.
<!ELEMENT mihtml (c1 | parrafo | imagen)*>
Este elemento en XML se escribirá por ejemplo:
<mihtml>
<parrafo>....</parrafo>
<parrafo>....</parrafo>
</mihtml>
Contenido mixto
También es posible combinar los dos últimos casos y declarar la especificación de contenido, de manera que un elemento tenga texto y otros elementos.
En nuestro ejemplo es el caso del elemento para, que puede estar formado de texto y de elementos negrita.
<!ELEMENT parrafo (#PCDATA|negrita)*>
Como podemos observar, no tenemos más que combinar la palabra clave #PCDATA con los nombres de los elementos que contendra.
Este elemento en XML se escribirá por ejemplo:
<parrafo>Esto es un <negrita>parrafo</negrita></parrafo>
o
<parrafo>Esto es un parrafo</parrafo>
Posiblemente, el nombre de contenido mixto no sea el más adecuado, ya que como vemos en el ejemplo el modelo de contenido mixto no significa que siempre deban incluirse tanto elementos como texto.
También es posible indicar que un elemento puede contener cualquier elemento o carácter. Esto se consigue mediante la palabra clave ANY. Es muy poco utilizado, aunque puede ser muy útil durante el proceso de creación de una DTD cuando todavía no tenemos muy claro cuál será el contenido de un elemento.
Conectores de grupo
El modelo de contenido puede contener más de un elemento y,por tanto, se necesita
información adicional que especifica el orden en el que aparecen. Para ello utilizamos los
contectores de grupo. En el XML hay dos posibles conectores de grupo:
- , indica que deben aparecer en ese orden.
- | indica que sólo uno de los componentes puede aparecer.
Si nos fijamos en nuestro ejemplo, utilizamos esencialmente el conector | mediante el cual indicamos que el autor del documento XML puede elegir entre un elemento u otro.
Por ejemplo, en:
<!ELEMENT mihtml (c1 | parrafo | imagen)*>
estamos indicando que dentro del elemento mihtml el autor puede poner o el elemento c1, o el elemento parrafo, o el elemento imagen.
Es decir, que los siguientes ejemplos son todos válidos.
<mihtml>
<parrafo>...</parrafo>
</mihtml>
<mihtml>
<c1>...</c1>
</mihtml>
<mihtml>
<imagen/>
</mihtml>
Otro tema es el indicador ,* que nos indica que ese modelo de contenido se puede repetir y que, por tanto, esos tres elementos pueden aparecer tantas veces como quieran.
En cambio el conector "," establece una secuencia que debe seguirse. Imaginemos que en nuestro pequeño HTML queremos incluir la posibilidad de tener listas ordenadas y que éstas puedan estar ordenadas. Si al elemento lista ordenada lo identificamos mediante el elemento lo y a sus entradas "items" mediante el elemento item, su declaración en la DTD quedaría de la siguiente manera:
<!ELEMENT lo (item, (lo|item)*)>
<!ELEMENT item (#PCDATA)>
Mediante el conector ,, estamos indicando que dentro de un lo en primer lugar debe haber un item y que luego puede venir otro "item" o empezar otra lista. Un texto XML que se ajuste a esta definición podría ser:
<lo>
<item>Texto</item>
<item>Texto</item>
<lo>
<item>Texto</item>
<item>Texto</item>
</lo>
</lo>
Indicadores de aparición
Se utilizan para indicar cuántas veces puede aparecer el elemento referenciado
en el modelo de contenido. Hay tres indicadores de aparición:
- + Indica que puede haber una o más apariciones del elemento.
- ? Indica que puede haber a lo más una o ninguna aparición del elemento.
- * Indica que el elemento puede estar ausente, una o más veces.
Como ya hemos explicado, dentro del elemento mihtm, los elementos c1, parrafo o elemento imagen pueden aparecer en el orden que quieran, pero tantas veces como quieran, o incluso ninguna. Esta última característica la indicamos mediante el indicador *.
Pero imaginemos que queremos que el primer elemento de una lista ordenada no sea siempre el elemento item, sino que queremos permitir que sea lo. En tal caso podríamos definir el elemento de la siguiente manera:
<!ELEMENT lo (item?, (lo|item)*)>
Donde con item? estamos indicando que puede aparecer 0 o 1 veces y que, por tanto, el siguiente ejemplo es válido.
<lo>
<lo>
<item>Texto</item>
<item>Texto</item>
</lo>
</lo>
Aunque en este caso conseguiríamos el mismo efecto definiendo el elemento de la siguiente manera:
<!ELEMENT lo (lo|item)*>
Añadiendo atributos a los elementos
Del mismo modo que los elementos, los atributos se declaran en la DTD utilizando una
sintaxis bastante similar. En este caso se realiza mediante el término ATTLIST, que en el
comienzo de una declaración indica que es una especificación de una lista de atributos.
<!ATTLIST nombre_elemento
nombre_atributo tipo valor_defecto>
Como podemos observar, la primera muestra indica el elemento sobre el cual se van a definir
los atributos y, a continuación, viene una tripla de datos en los que indicamos:
- El nombre del atributo
- El tipo
- Y su valor por defecto.
Esta tripla se puede repetir tantas veces como queramos dentro de la declaración,
es decir, podemos declarar una lista de atributos, de ahí su nombre.
Un ejemplo de definición de atributos para nuestro elemento imagen podría ser:
<!ATTLIST imagen
direccion CDATA #REQUIRED
alineacion (izquierda, centrada, derecha) "izquierda">
Tipo
Una utilidad importante de los atributos es que mediante el tipo podemos hacer cumplir al elemento obligaciones léxicas o semánticas. Las obligaciones léxicas son por ejemplo "este atributo debe contener sólo números" y las semánticas son "este atributo debe contener el nombre de una entidad declarada". Evidentemente estas obligaciones son muy útiles, ya que nos permiten garantizar la integridad de algunos de los valores de los atributos, pero la verdad es que son bastante limitadas y en muchas ocasiones insuficientes.
Los tipos de atributos pueden ser:
- CDATA
- NMTOKEN
- NMTOKENS
- ENUMERADOS
- NOTATION
- ID
- IDREF
- IDREFS
- ENTITY
- ENTITYS
En teoria las posibilidades son muchas, aunque luego en la práctica sin duda alguna los más utilizados son los CDATA y el ID.
CDATA
Es el tipo de atributo más sencillo.Mediante su utilización estamos indicando que el valor del atributo debe ser de tipo carácter. Es, por tanto, de todos los tipos el que menos obliga.
Al especificar el atributo direccion de nuestro elemento imagen:
<!ATTLIST imagen
direccion CDATA #REQUIRED
...
estamos indicando que el valor del atributo dirección puede llevar cualquier tipo de carácter.
ID
Mediante este tipo de atributo identificamos de forma unívoca un elemento del documento XML. Su valor debe ser único en el documento.
Imaginemos que queremos identificar de forma unívoca los elementos c1, de manera que luego sean fácilmente identificables y referenciables. Esto lo tendríamos que indicar:
<!ATTLIST c1
id ID #REQUIRED
...
IDREF
Está estrechamente ligado al tipo de atributo ID, y mediante su utilización estamos indicando que hacemos referencia al valor de algún atributo ID.
NMTOKEN
Estos atributos se parecen en parte a los atributos CDATA. La principal diferencia es que sólo aceptan lo caracteres.
ENUMERADOS
Ofrecen al usuario la posibilidad de elegir entre un número reducido de valores.
Es el caso, por ejemplo, del atributo alineacion en el elemento imagen:
<!ATTLIST imagen
.....
alineacion (izquierda, centrada, derecha) "izquierda">
Donde estamos indicando que los únicos valores permitidos para el atributo alineacion son: izquierda, centrada y derecha.
Valor por defecto
La última parte de la especificación sirve para indicar al parser cómo debe
interpretar la ausencia de atributo.
Ya hemos visto que en este lugar podemos indicar, el valor que puede tener
por defecto.
Pero en el caso de que esto no sea así,indicamos al parser cómo debe interpretar
la ausencia de atributo con las siguientes palabras reservadas:
- #REQUIREDestamos indicando que es obligatorio colocar un valor en el atributo.
- #IMPLIED, indicamos que el valor para ese atributo es opcional, puede tener o
no tener.
- #FIXED, estamos fijando el valor del atributo y el documento no será válida si
a ese atributo le damos un valor diferente al especificado.