viernes, junio 22, 2007

¿Otro post no? XML for Mayor!

Como veo que la cosa está más muerta que un cordero la noche después del fin del Ramadán digo...¿voy a escribir no? ... pero ... ¿qué coño escribo?

Pues como últimamente he estao aprendiendo cosillas sobre XML, RDF, RDFa, JDOM, DOM, SAX, XML-RPC, SOAP, XSLT, SNMP, J2EE, J2ME, BGP, IPv6, y demás parafernalias (cómo mola escribir siglas, no importa que no tengas puta idea, quedas como un señor poniéndolas ;) ), pos me he decidío a contaros un poquillo de estas tecnologías en diferentes post por entregas. Si os aburro no tenéis más que decirlo.

Y pa empezar, vamos a introducirnos levemente en el maravilloso mundillo del XML.

Actualización(23/06/07):
Como los feeds (orígenes, RSS, como los queráis llamar) se envían mediante XML, paradojas de la vida, quien lea este post recibiéndolo desde un agregador probablemente no lo lea bien porque interpretará el código XML y el resultado será que no se le mostrarán las etiquetas, sólo su contenido. Por ello, por el momento y a estas alturas de la noche no se me ocurre más que entrar vía web para leerlo sin problemas. Mil perdones. ¿A alguien se le ocurre una solución?



XML

Mi descubrimiento de XML como metalenguaje para "casi todo" ha sido como encontrarse con un hermano perdido. Uno se pregunta...¿cómo coño no lo vi antes? ¿he estao tirando to este tiempo a la basura?

¿De ande ha salío ésto?

XML surge más o menos como una simplificación de SGML, que viene a ser un lenguaje un tanto más ambíguo pero mucho más extenso y rico. SGML se lo inventaron por allá por los "unites estates" cuando un grupo de editoriales decidieron que los autores tenían que definir el contenido de forma lógica mientras los editores se dedicaran a la presentación física que es pa lo que al fin y al cabo les pagan :). Así después de unos cuantos quebraderos de cabeza se llega a un estándar ISO con una especificación muuuuy compleja. Pero claro, esto pa los libros y un grupo reducido de gente dispuesta a andarse con rodeos está mu bien, pero pa Internet digamos que la cosa estaba chunga. Así surge una simplificación que aprovechaba la experiencia previa de SGML para orientarlo a Internet y que permitía fácilmente la definición de nuevos lenguajes (de ahí el eXtensible de "eXtensible Markup Language"). Sobre todo, lo que se buscaba era un lenguaje que fuese fácil de procesar, y a la vista está que lo consiguieron. Podíamos decir que con XML se consiguió un 80% de la funcionalidad de SGML con sólo un 20% de su complejidad. Todo un logro, ¿verdad?

Pa no confundirnos, y como a alguno ésto le puede sonar a HTML aclaremos que
XML == SGML--
pero...
XML != HTML++

Aunque la sintaxis XML pueda recordarnos a HTML (de hecho las versiones actuales de HTML son ya XML, más concretamente se le llama XHTML), XML presenta algunas diferencias con el tradicional HTML de to la vida. Algunos ejemplos son:
  • En HTML podíamos alegremente cerrar y abrir las etiquetas donde nos diese la gana, e incluso algunas ni cerrarlas, por lo que se suponía </p> por defecto. En XML ni de coña. Cada etiqueta que se abra debe ser cerrada adecuadamente, e importando y mucho el orden. Así mientras en HTML podíamos escribir <p><i>jeje</i></p>, en XML no se puede en aras de un procesamiento más simple y de más claridad.
  • Mientras en HTML los valores de los atributos podían o no ir entre "", en XML es estrictamente obligatorio que lo hagamos.
  • En HTML podíamos dejar un atributo vacío sin cerrar, pero en XML todo elemento se cierra. Por ejemplo:
    (HTML) <img src="http://www.blogger.com/...">
    (XML) <img src="http://www.blogger.com/..." /> (nótese que pa ahorrarse el curro de volver a poner la etiqueta con "/" delante, si el elemento es vacío se puede poner el símbolo "/" antes de cerrarlo).
Dicho ésto vamos a ver un ejemplo sencillico XML y sobre él ya vamos trabajando.

Veamos qué pinta tiene

<?xml version="1.0" encoding="UTF-8">
<!DOCTYPE empresa SYSTEM "empresa.dtd">

<!-- Definición de una empresa emprendedora, "así tó wapa" podíamos definirla-->
<empresa clase="wenaquetecagas" contacto="nidea@nidea-soluciones.com">
<nombre>N-IDEA. Nuevas Ideas</nombre>
<url tipo="web">http://www.nidea-soluciones.com</url>
<url tipo="blog">http://nidea-soluciones.blogspot.com</url>
<direccionpostal>C/ Tejuela, 25. Alcalá la Real (Jaén). CP: 23680</direccionpostal>
</empresa>


Como véis, es bastante intuitivo. Yo defino lo que quiero y con la lógica que yo quiero imprimiéndole semántica a lo que escribo. De hecho sin saber programar una persona que leyera el código de arriba muy probablemente comprendería el mensaje. Ésa es la idea.

Pero vamos a lo que nos ocupa. Bueno, aquí tenemos varias cosas. Primero tenemos
<?xml version="1.0" encoding="UTF-8">
Ésta es lo que se llama una "processing instruction", pero además es una especial. Es la que debe contener todo documento XML al principio. Ántes de ella no se puede escribir nada, ni siquiera comentarios, para que el documento sea válido. Las processing instruction sirven para pasarle información a la aplicación que usa el documento XML. Normalmente su sintaxis es:
<?Programa Instrucciones?>
Como por ej: <?JAVA_OBJECT JAR_FILE="/nidea/mijar.jar"?>
Por supuesto, para no confundir al bicho, está prohibido empezar la processing instruction con "xml" ya que este nombre está reservado para el principio del documento como habéis visto.
Lo que sigue a "xml" son dos atributos de nombre version y encoding, y de valores 1.0 y UTF-8 respectivamente. Aunque os lo podéis imaginar, son la versión y la codificación del documento. La version es obligatoria que sea 1.0 (creo), y que aparezca siempre, pero la codificación puede no aparecer o puede ser distinta. Por ejemplo, un tipo de codificación muy típica es la ISO-8859-1 que viene a ser la que define los caracteres españoles específicamente. La UTF-8 es también llamada Unicode-8 y es la que he usao en este caso.

Siguiente cosa rara que vemos es...
<!DOCTYPE empresa SYSTEM "empresa.dtd">

Es una etiqueta especial ya que como se puede observar no sigue la sintaxis de xml para las etiquetas. No va cerrada, el nombre de la etiqueta comienza por ! en lugar de por letra o "_" y tiene espacios. Entonces...¿qué #!*+ es? Pues se trata de la definición del tipo de documento. Como ésto es sólo una breve introducción no entraré en detalles, pero es necesario saber que debe apuntar al elemento raiz del documento xml (lo que sigue a !DOCTYPE, en nuestro caso empresa) y al DTD del documento, que viene a ser un fichero que especifica la estructura de nuestro documento xml, qué elementos pueden ir dentro de otros, qué tipo de datos se acepta en cada elemento, cuántas veces puede aparecer un elemento, etc. Pero eso ya lo veremos luego. En nuestro caso, el DTD está en la misma carpeta del documento xml y se llama "empresa.dtd".

Después vemos un comentario. Es eso de...
<!-- Definición de una empresa emprendedora, "así tó wapa" podíamos definirla-->
Pos eso, se trata de un comentario. Algo que el/la programador/a escribe para que no sea interpretado por los programas que hagan uso del documento, pero que puede servir para hacer más legible el mismo o para explicar algunos detalles específicos a otros/as programadores/as que puedan leer nuestro xml. En ocasiones también se usa para ocultar elementos a los programas. En fin, usarlos mola, pero no usarlos no hace tu documento no válido.

Y luego viene el documento en sí, con sus etiquetas, sus atributos y demás. De eso creo que poco hay que explicar. La cosa está en imaginar de forma lógica la información que queremos representar y luego escribirla con coherencia. Si queremos representar en un documento una empresa que puede ser de varias clases y que tendrá un único e-mail de contacto, una forma de representarlo sería con la que escogí arriba:
<empresa clase="wenaquetecagas" contacto="nidea@nidea-soluciones.com"></empresa>
pero ahí ya está vuestra imaginación y el tipo de datos que queráis representar. Si además sabemos que una empresa tiene un nombre, nos podemos inventar un nuevo elemento que esté dentro de "empresa" y cuya etiqueta sea "nombre". Si sabemos que la empresa tendrá urls de varios tipos y múltiples, una fórmula puede ser crear otros tantos elementos también dentro de "empresa" de etiqueta "url" y con un atributo "tipo" que defina el tipo de url que es (página web, blog, wiki...). Si por último sabemos que las empresas representadas por este tipo de documento pueden tener una dirección postal que queramos representar, nos podemos imaginar un último elemento "direccionPostal" que almacene esta información. Pero lo que os dije antes, todo es imaginar e inventar. Ahí los creadores sois vosotros/as.

Bueno, visto un ejemplo práctico sobre el que habremos visto la dinámica de XML, vamos a ver algunas cuestiones específicas de los elementos y los atributos.

Elementos y Atributos

Los elementos deben comenzar su nombre por letra o underscore (_) seguido de alguna combinación de letra, underscore, números, puntos, dos puntos o guiones. No puede contener espacios en blanco y no puede comenzar por "xml" en ninguna de sus variantes (xml, xmL, xMl, xML, Xml, XmL, XMl o XML). En principio no existe longitud máxima para el nombre aunque hay que tener cuidado con algunos parsers de nivel superior que puedan tenerlo.

Los atributos se definen en la etiqueta de comienzo de un elemento. Definen pares nombre="valor". No pueden estar duplicados dentro de la misma etiqueta, usan para su nombre las mismas reglas que los elementos y son obligatorias las comillas para determinar el valor. Como es lógico, el símbolo de las comillas (") no puede aparecer en el valor del atributo, para lo cual se utilizará la entidad predefinida & quot; (sin el espacio entre & y quot;. No lo junto porque entonces vuestro navegador os lo mostraría como " y entonces habríamos hecho un pan con unas hostias).


DTD

Veamos lo último que nos falta para poder definirnos nuestro lenguaje XML a nuestro gusto. Pongamos que vamos a definir un nuevo lenguaje que llamaremos NideaML.
Como hemos visto antes, NideaML es un lenguaje sencillico y que sirve para definir una empresa dado su nombre, clase, correo-e de contacto, urls de varios tipos y dirección postal. Si dejáramos nuestro documento anterior tal cual eliminando la sentencia de !DOCTYPE, ya no sería NideaML, sería XML normalico y corriente porque no existirían restricciones que impidieran a nadie meter otros atributos en el documento o inventarse nuevos elementos, o no colocarlos en su debido orden. Si no hay DTD, se asume que cualquier cosa puede ir dentro de cualquier cosa y se admite cualquier tipo de elemento. ¿Pero cómo podemos añadir estas restricciones? Como ya os dije antes, para eso está aquí nuestro amigo el DTD.

Como antes, no hay mejor forma de aprender algo en cualquier tipo de programación que viendo algo programado, así que os mostraré cómo quedaría el DTD llamado empresa.dtd, que quedaría como sigue...

<!ELEMENT empresa (nombre, url*, direccionPostal?)>
<!ATTLIST empresa
clase CDATA #REQUIRED
contacto CDATA #REQUIRED>
<!ELEMENT nombre (#PCDATA)>
<!ELEMENT url (#PCDATA)>
<!ATTLIST url
tipo (web | blog | wiki | proyecto) "web">
<!ELEMENT direccionPostal (#PCDATA)>

¿Qué? ¿Cómo lo veis? ¿Bonito no? :).
Se puede intuir más o menos la sitaxis, pero vayamos poco a poco. De lo primero que ya os habréis percatao es que no se trata de XML, se parece más a nuestro querido !DOCTYPE que al resto de lo que hemos visto.

Bien, queremos definir qué elementos se permiten, cuáles están dentro de cuáles, qué atributos tienen, si son o no obligatorios y de qué tipo son.

Empecemos por los elementos. Los elementos se declaran con !ELEMENT seguido de su nombre y entre paréntesis el tipo de datos que van a contener indicando cuántas veces van a ocurrir. El nombre del elemento sigue las reglas que ya citamos antes, y el tipo de datos que van a contener pueden ser otros elementos (se pone el nombre de éstos), texto normal (#PCDATA), una combinación con expresiones regulares de las anteriores (ej: nombre | #PCDATA | (otroNombre, otroMas) ), cualquier cosa (ANY) o nada (EMPTY).
El número de ocurrencias de cada cosa que puede entrar en nuestro elemento lo definen unos caracteres que se añaden al final del nombre del elemento/expresión regular. Veamos nuestros símbolos para las expresiones regulares:
si no ponemos nada implica que ocurre sólo una vez
+ indica una o más veces
* indica cero o más veces
? indica cero o una vez
() indica agrupamiento
| indica disyunción
, indica secuencia ordenada
Vamos pues a echarle un vistazo a nuestro ejemplo para ver eso qué implica.

<!ELEMENT empresa (nombre, url*, direccionPostal?)>
Según lo dicho antes, esta declaración define un elemento de nombre "empresa" que puede contener a su vez otros elementos, y sólo otros elementos, no puede tener texto plano; y además estos elementos tienen que ser de tipo "nombre","url" y "direccionPostal"; y además tienen que aparecer en este orden; y además ocurrirá que,
"nombre" aparecerá sólo una vez,
"url" puede aparecer cuantas veces quiera o no aparecer,
"direccionPostal" puede aparecer una vez o no aparecer

¿Fácil no? Ahora vamos con los atributos
Los atributos se declaran con !ATTLIST seguido del nombre del elemento al que pertenecen y seguido de la lista de atributos que puede contener este elemento.
La lista de atributos se escribe siguiendo triplas del siguiente modo
nombre_atributo tipo_atributo valor_por_defecto
Ocasionalmente puede ir entre el tipo de atributo y su valor por defecto la obligatoriedad o no de que aparezca el atributo, de modo que
#REQUIRED significa que el atributo es obligatorio
#IMPLIED significa que el atributo no es obligatorio
#FIXED significa que el atributo está fijo al valor que ponemos por defecto y el programador del documento xml no puede modificarlo. Si lo hiciera esta valor es ignorado prevaleciendo el del DTD.
El valor por defecto sólo tiene sentido cuando el atributo es #FIXED o #IMPLIED. En el caso concreto de #FIXED además es obligatorio. La cosa es que si ponemos a un atributo #REQUIRED se supone que es obligatorio, luego el programador pondrá un valor sí o sí, ¿para qué íbamos a darle un valor por defecto si siempre sería machacado por el del programador XML?
Los tipos de datos pueden ser:
CDATA -> Similar al #PCDATA de los elementos.
Enumerated -> Tienen su sintaxis especial, es el que hemos usado en el ejemplo para el atributo "tipo" del elemento "url". Consiste en una expresión de posibles valores separados por (|) donde el programador/a elegirá uno de ellos.
ID -> Asocia al elemento un identificador único.
IDREF -> Referencia a un ID.
IDREFS -> Lista de IDREF separados por espacio.
NMTOKEN -> Especifican identificadores.
NMTOKENS -> Especifican listas de identificadores.

Si todo esto lo aplicamos a nuestro ejemplo particular...
<!ATTLIST empresa
clase CDATA #REQUIRED
contacto CDATA #REQUIRED>

...implica que estamos tratando con la lista de atributos del elemento "empresa"; que además puede tener atributos tipo clase o tipo contacto; que además clase son datos normales y corrientes y es obligatoria su aparición; y que además contacto también tendrá como valores datos normales y será obligatoria su especificación en el documento XML.

<!ATTLIST url
tipo (web | blog | wiki | proyecto) "web">

...implica que estamos tratando con la lista de atributos del elemento "url"; que además sólo tendrá el atributo "tipo"; que éste podrá ser igual a "web" o "blog" o "wiki" o "proyecto" y que en caso de no encontrarse el valor por defecto será de "web".

Y bien, yo creo que como introducción a lo que puede ser XML y su definición mediante DTDs, ésto ya está. Ya podéis haceros vuestro lenguaje MiracomomoloML para definir todo lo que se os ocurra. ¿Y para qué? Pues por ejemplo una utilidad muy buena es la de pasarle al documento una hoja de estilo XSLT y transformarlo directamente en una página web con un formato determinado, que puede servirnos para crear páginas web dinámicamente en una máquina a partir de una aplicación que recoja unos datos de un formulario web, o para utilizar sistemas como DOM o JDOM para recorrer la información recogida en el formulario web y convertida a XML y usarla para hacer otra cosa, o para crear apliciones...¡yo qué se! yo ya os he contao como funciona, ahora ¡a buscarle utilidades propias, coño! :).

Espero que os sea de utilidad. Si así es, prometo volver para contaros un poco de XMLSchema, que vienen a ser los sucesores de los DTD y que permiten más versatilidad y especificidad en las definiciones.

+info:
http://www.w3.org
http://www.xml.com

http://www.xmlinfo.com

2 comentarios:

Manuel Cardenas Thorlund dijo...

Menos mal que escribes tú. Estoy liadísimo con el curro.

De todas formas tu artículo sobre XML me ha picado el gusanillo y voy a escribir un artículo sobre AJAX.

En breve, AJAX para principiantes!!!

Nacho Foche dijo...

¡Mola! La verdad es que siempre quise aprender de una vez por toas AJAX. Por cierto, cuando lo hagas, ¿puedes comentar cómo dar con AJAX una solución a una página accesible según el W3C? Imagino que usar AJAX también lo permite, pero como no tengo Ni-IDEA pos way si lo comentaras ;).
Yo ahora estoy escribiendo otro post de J2EE, pero cuando acabe tengo intención de escribir algo sobre accesibilidad en linux para ciegos (estoy llevando un trabajo dirigido que consiste en establecer un puesto informático linux accesible para ciegos, ya os contaré más detalladamente).