jueves, 3 de julio de 2008

Java y XML

El lenguaje XML se ha consolidado como uno estándares por excelencia en el intercambio de datos. Es ampliamente usado en el mundo de Internet, pero también lo es en otros tipos de aplicaciones como hojas de cálculo, bases de datos, etc. El objetivo de este post no es comentar qué es XML y las ventajas que su uso conlleva. Para eso hay otras páginas que lo explican muy bien. El objetivo de esta serie posts (serán más de uno) es, una vez te hayas familiarizado con XML, explicar cómo hacer uso de este metalenguaje desde aplicaciones Java.


Las APIs que yo he usado para el tratamiento de XML son las siguientes: SAX, DOM, JDOM y XOM. Tanto SAX(Simple API for XML Parsing) como el estándar DOM(Document Object Model) fueron implementadas por Java mediante la API JAXP (Java Api for XML Processing). Son los más antiguos y desde mi punto de vista arcaicos.

Por un lado SAX está hecho sólo para "parsear" (procesar) documentos XML y no permite la creación de los mismos. Por otro DOM, aunque ya permite creación de documentos XML, es un estándar independiente del lenguaje (JAXP implementa este estándar en Java), con las limitaciones que esto conlleva. JDOM y XOM son APIs basadas en DOM pero diseñadas específicamente para Java y por tanto son más eficientes y más fáciles de usar desde el punto de vista del programador Java. En ciertas ocasiones, operaciones de 10 líneas en DOM se implementan en 2 líneas de código en JDOM o XOM.

Podemos dividir estas 4 APIs en dos grupos: SAX en un lado y DOM, JDOM y XOM en otro. La diferencia estriba en que mientras SAX implementa un procesado de documentos de acceso en serie y basado en eventos, el resto mapea el documento XML en un arbol de objetos.

Dicho de otro modo, SAX procesa el documento xml secuencialmente y conforme se va encontrado partes del xml (comienzo de una etiqueta, fin de una etiqueta) van saltado eventos que son recogidos por una clase (manejador de eventos) la cuál actua de una forma u otra en función del evento. Por ejemplo, veremos más adelante que en el evento comienzo de una etiqueta se pueden leer los atributos de la misma o que en el evento fin de una etiqueta se puede leer el contenido de ella.

Por otro lado DOM, JDOM y XOM procesan el documento XML al completo y generan un arbol de nodos que representa el documento XML. Este árbol puede ser leído, modificado y de nuevo serializado a cadena o fichero XML. Incluso es posible crear un árbol desde cero, es decir, no hay que partir de un fichero o documento XML ya creado.

Como se puede deducir el uso de DOM, JDOM y XOM es más potente que el de SAX. Aunque como todo, nada es del todo malo o del todo bueno. El consumo de memoria de DOM,JDOM y XOM es mucho mayor que el de SAX, ya que mantienen todo el arbol de nodos en memoria. SAX puede venir bien para el procesado de documentos XML muy grandes ya que va procesando el XML evento por evento.

En próximos posts entraré en más profundidad en cada una de estas 4 APIs y expondré ejemplos de uso de las mismas. Espero que sean de utilidad para alguien:

8 comentarios:

Anónimo dijo...

Hola, tengo una pregunta para el creador de este blog. Veras, yo tengo que hacer una GUI a partir de un archivo XML que es enorme. Tambien me han proporcionado una serie de archivos DTD relacionados con ese XML que no se si seria necesario procesar o no. Mi pregunta es: Si finalmente lo que yo quiero es tener un programa que me muestre en forma de GUI todo el contenido del XML de modo que yo pueda leer su contenido y hacerle modificaciones (a traves de esta GUI que he programado) que deberia usar, SAX o DOM?
Muchisimas gracias!

Xela dijo...

Hola,

la clave de tu pregunta está en tu frase "leer su contenido y hacerle modificaciones". Si lo que quieres es modificar XML tan solo te queda la posibilidad de usar DOM o alguna de las otras "apis DOM" (léase JDOM o XOM) ya SAX no te permite modificar XML. SAX sólo sirve para parsear(leer) XML.

Sin embargo, dado que tu XML es grande, hay algo que puedes hacer para mejorar el rendimiento de tu aplicación. Se trata de usar SAX a la hora de construir el árbol de nodos DOM. Esto te da la ventaja de que no tienes que cargar todo el fichero XML en memoria ya que el procesado que hace SAX es secuencial. Si usas JDOM, esto lo puedes conseguir usando SAXBuilder para construir el árbol de nodos. Te recomiendo que leas el post de JDOM.

Aún así, esto no te libra de que tu aplicación consuma mucha memoria (RAM), ya que aunque evites mantener el fichero XML en memoria al completo, muy probablemente tu enorme fichero XML producirá un también enorme árbol de nodos DOM, éste sí almacenado al completo en memoria. Ante esto tienes dos posibles soluciones:

1. Aumentar la memoria máxima del proceso Java. (Opción -Xmx de la máquina virtual Java)

2. Generarte un árbol de nodos(objetos) personalizado y optimizado para tu aplicación, en el cuál tan solo almacenes lo imprescindible. Esto te evitará mantener en memoria ciertos datos que probablemente para tu aplicación puedan considerarse como morralla.

Me refiero a que si en el XML almacenas por ejemplo información sobre los paneles de tu aplicación, proceses el XML con SAX y a partir de los datos que SAX te vaya dando te vás creando una serie de objetos Panel que estarán relacionados entre sí y/o con otros datos que vengan en el XML.

Sin duda, esto te reducirá la cantidad memoria necesaria para mantener la configuración de tu aplicación cargada en memoria. Sin embargo, el ahorro respecto al árbol DOM dependerá de tu aplicación. Debes ser tú quien debe valorar si el ahorro es tal que merezca la pena desarrollar un árbol de nodos propio o por el contrario usar algo ya hecho a pesar de consumir algo más de memoria.

Espero que esto te haya aclarado algo.

De todas formas, si alguien tiene algo que aportar o no está de acuerdo en algo, le invito a que participe y enriquezca el post con sus comentarios.

Xela dijo...

Se me olvidó comentar que yo suelo mantener la configuración de mi aplicación en memoria mediante objetos propios. Sin embargo, como mis ficheros de configuración no suelen ser grandes comparado con la memoria que puede llegar a consumir la aplicación, por comodidad y mantenibilidad suelo usar JDOM o XOM para cargar los XMLs y a partir de XPath voy obteniendo la información que necesito del XML y generando mis propios objetos de configuración. Una vez cargada la configuración en mis objetos, el árbol DOM es eliminado de la memoria por el Garbage Collector

Si mis ficheros XML fueran muy muy grandes, me plantearía usar únicamente SAX para cargar la configuración y pasarla a mis propios objectos. Sin embargo, en mi caso no se me ocurre ninguna circunstancia en la que pueda tener ficheros de configuración tan grandes. ;-)

Anónimo dijo...

Guau, muchisimas gracias por tus comentarios! Yo es que aun soy muy pardillo en todo este tema y en muchas cosas me pierdo... Creo que usare solo DOM por el momento, porque andar mezclando me parece complicado. Aun estoy mirando el ejemplo que has puesto en otro post, a ver si de ahi puedo sacar cosas practicas que me sirvan. En todo caso muchas gracias, se nota que dominas mogollon y esto ayuda a otras personas.

Xela dijo...

Mi recomendación es que uses JDOM. Te será mucho más sencillo. Ya verás que conforme vayas avanzando llegas a plantearte los problemas que te comento en el primer comentario.

Fran dijo...

Muchas gracias Xela! Ahi sigo peleando... me he puesto a mirar tu post del JDOM. Me queda una duda que te la pregunto en ese post por resultar mas conveniente, creo yo.

CmaJ dijo...

Muy buena introducción al farragoso del procesamiento XML en Java.

Enhorabuena y muchas gracias por compartir.

Danielezn dijo...

Hola que tal, muy interesante, tu particularmente que me recomiendas para leer grafos a partir de xml? Sax, Dom, JDOM, XOM, ?