APIs de Java para XML

El API Java para Proceso de XML (JAXP) hace fcil el proceso de datos XML con aplicaciones escritas en el lenguaje Java. JAXP contiene los analizadores estndars SAX (Simple API for XML Parsing) y DOM (Document Object Model) para que podamos elegir entre analizar nuestros datos como streams de eventos y construir una representacin de objetos con ellos. La versin 1.1 de JAXP tambin soporta el estndar XSLT (XML Stylesheet Language Transformations), dndonos control sobre la representacin de los datos y permitindonos convertir los datos a otros documentos XML o a otros formatos, como a HTML. JAXP tambin proporciona soporte para espacios de nombres, permitindonos trabajar con DTDs que de otra forma tendran conflictos de nombrado.

Diseado para ser flexible, JAXP nos permite usar cualquier analizador compatible XML desde dentro de nuestra aplicacin. Esto lo hace con algo llamado capa de conectividad, que nos permite enchufar una implementacin de los APIs SAX o DOM. La capa de conectividad tambin nos permite enchufar un procesador XSL, lo que nos permite controlar la forma en que se muestran los datos. La Implementacin de Referencia 1.1 de JAXP (disponible en http://java.sun.com/xml) proporciona el procesador de XSLT Xalan y el analizador Crimson, mbos desarrollados conjuntamente entre Sun y la Fundacin de Software Apache, que proporciona software open-source.

.El API SAX

SAX define un API para un analizador basado en eventos. Estar "basado en eventos" significa que el analizador lee un documento XML desde el principio hasta el final, y cada vez que reconoce una sntaxis de construccin, se lo notifica a la aplicacin que lo est ejecutando. El analizador SAX notifica a la aplicacin llamando a los mtodos del interface ContentHandler. Por ejemplo, cuando el analizador encuentra un smbolo ("<"), llama al mtodo startElement; cuando encuentra caracteres de datos, llama al mtodo characters; y cuando encuentra un smbolo ("</"), llama al mtodo endElement, etc. Para ilustrar, echemos un vistazo al documento XML del ejemplo de la primera seccin y veamos que hace el analizador en cada lnea. (Por simplicidad, no se han incluido las llamadas al mtodo ignorableWhiteSpace.)

<priceList> [el analizador llama a startElement]
    <coffee> [el analizador llama a startElement]
        <name>Mocha Java</name> [El analizador llama a startElement, characters, y endElement]
        <price>11.95</price> [el analizador llama a startElement, characters, y a endElement]
    </coffee> [el analizador llama a endElement] 

Las implementaciones por defecto de los mtodos que llama el analizador no hacen nada, necesitamos escribir un subclase que implemente los mtodos apropiados para obtener la funcionalidad que queremos. Por ejemplo, supongamos que queremos obtener el precio por libra del caf "Mocha". Escribiriamos una clase extendiendo DefaultHandler (la implementacin por defecto de ContentHandler) en la que escribiramos nuestras propias implementaciones de los mtodos startElement y characters.

Primero necesitamos crear un objeto SAXParser desde un objeto SAXParserFactory. Llamaramos al mtodo parse sobre l, pasndole la lista de precios y un ejemplar de nuestra nueva clase handler (con sus nuevas implementaciones de los mtodos startElement y characters). En este ejemplo, la lista de precios es un fichero, pero el mtodo parse tambin puede aceptar una gran variedad de fuentes de entrada, incluyendo objetos InputStream, URL, y InputSource.

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser SAXParser = factory.newSAXParser();
SAXParser.parse("priceList.xml", handler);

El resultado de llamar al mtodo parse depende, por supuesto, de como estn implementados los mtodos en handler. El analizador SAX atravesar el fichero priceList.xml lnea a lnea, llamando a los mtodos apropiados. Adems de los mtodos ya mencionados, el analizador llamar a otros mtodos como startDocument, endDocument, ignorableWhiteSpace, y processingInstructions, pero estos mtodos tambin tienen sus implementaciones por defecto que no hacen nada.

Las siguientes definiciones de mtodos muestran una forma de implementar los mtodos characters y startElement para que puedan encontrar e imprimir el precio del caf Mocha Java. A causa de la forma en que trabaja el analizador SAX estos mtodos trabajan juntos para buscar en el elemento name, los caracteres "Mocha Java", y el elemento price que sigue inmediantemente a "Mocha Java". Estos mtodos usan tres banderas para seguir la pista de las condiciones que han encontrado. Observa que el analizador SAX tendr que llamar a estos mtodos ms de una vez antes de se alcancen las condiciones para imprimir el precio:

public void startElement(..., String elementName, ...){
    if(elementName.equals("name")){
        inName = true;
    } else if(elementName.equals("price") && inMochaJava ){
        inPrice = true;
    inName = false;
    }
}

public void characters(char [] buf, int offset, int len) {
    String s = new String(buf, offset, len);
    if (inName && s.equals("Mocha Java")) {
        inMochaJava = true;
        inName = false;
    } else if (inPrice) {
        System.out.println("The price of Mocha Java is: " + s);
        inMochaJava = false;
        inPrice = false;
    }
}

Una vez que el analizador ha encontrado el elemento coffee "Mocha Java", aqu tenemos el estado despus de la siguientes llamadas a mtodos:

  • siguiente llamada a startElement -- inName es true
  • siguiente llamada a characters -- inMochaJava es true
  • siguiente llamada a startElement -- inPrice es true
  • siguiente llamada a characters -- imprime el precio

El analizador SAX puede realizar validacin mientras analiza los datos XML, lo que significa que chequea si los datos siguen las reglas especificadas en el DTD de los documentos XML. Una analizador SAX ser con validacin si fue crado mediante un objeto SAXParserFactory con la validacin activada. Esto se hace para la factora de objetos SAXParserFactory en la siguiente lnea de cdigo:

factory.setValidating(true);

Para que el analizador sepa qu DTD utilizar para la validacin, el documento XML debe referenciar el DTD en su declaracin DOCTYPE. Esa declaracin debera ser similar a esta:

<!DOCTYPE PriceList SYSTEM "priceList.DTD">

.El API DOM

El API "Document Object Model" (DOM), definido por el grupo de trabajo DOM de la W3C, es un conjunto de interfaces para construir una representacin de objeto, en forma de rbol, de un documento XML analizado. Una vez que hemos construido el DOM, podemos manipularlo con mtodos DOM como insert y remove, igual que manipularamos cualquier otra estructura de datos en forma de rbol. As, al contrario que un analizador SAX, un analizador DOM permite acceso aleatorio a piezas de datos particulares de un documento XML. Otra diferencia es que con un analizador SAX, slo podemos leer un documento XML, mientras que con un analizador DOM, podemos construir una representacin objeto del documento y manipularlo en memoria, aadiendo un nuevo elemento o eliminando uno existente.

En el ejemplo anterior, usamos un analizador SAX para buscar slo un dato en un documento. Usando un analizador DOM hubieramos tenido que tener el modelo del objeto del documento completo en memoria, los que generalmente es menos eficiente para bsquedas que implican unos pocos tems, especialmente si el documento es largo. En el siguiente ejemplo, aadimos un nuevo caf a la lista de precios usando un analizador DOM. No podemos usar una analizador SAX para modificar la lista de precios porque slo permite la lectuda de datos.

Supongamos que queremos aadir el caf "Kona" a la lista de precios. Leeremos el fichero XML de la lista de precios en un DOM y luego insertamos el nuevo elemento coffee, con su nombre y su precio. El siguiente fragmento de cdigo crea un objeto DocumentBuilderFactory, que luego es usado para crear el objeto DocumentBuilder. Luego el cdigo llama al mtodo parse sobre el builder, pasndole el fichero "priceList.xml".

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("priceList.xml");

En este punto, el documento es una representacin DOM de la lista de precios situada en la memoria. El siguiente fragmento de cdigo aade un nuevo caf (con el nombre "Kona" y el precio de 13.50) al documento de la lista de precios. Como queremos aadir el nuevo caf justo antes del caf cuyo nombre es "Mocha Java", el primer paso es obtener una lista de elementos name e iterar a travs de la lista para encontrar "Mocha Java". Usando el interface Node incluido en el paquete org.w3c.DOM, el cdigo crea un objeto Node para el nuevo elemento coffee y tambin nuevos nodos para los elementos name y price. Estos dos elementos contienen los datos, por eso el cdigo crea un objeto TextNode para cada uno de ellos y aade los nodos de texto a los nodos que representan los elementos name y price.

NodeList list = document.getElementsByTagName("name");
Node thisNode = list.getItem("name");
// loop through list
Node thisChild = thisNode.getChildNode();
if(thisNode.getFirstChild() instanceof org.w3c.DOM.TextNode) {
    String data = thisNode.getFirstChild().getData();
}
if (data.equals("Mocha Java")) {             // new node will be inserted before Mocha Java
    Node newNode = document.createElement("coffee");
    Node nameNode = document.createElement("name");
    TextNode textNode = document.createTextNode("Kona");
    nameNode.appendChild(textNode);
    Node priceNode = document.createElement("price");
    TextNode tpNode = document.createTextNode("13.50");
    priceNode.appendChild(tpNode);
    newNode.appendChild(nameNode);
    newNode.appendChild(priceNode);
    thisNode.insertBefore(newNode, thisNode);
    }

Obtenemos una analizador DOM que tiene validacin de la misa forma que un analizador SAX validante: llamamos a setValidating(true) sobre una factora de analizadores DOM antes de usarla para crear nuestro analizador DOM, y nos aseguramos de que el documento XML referencia su DTD en la declaracin DOCTYPE.

.Espacios de Nombres XML

Todos los nombres en un DTD son nicos, as se evita la ambiguedad. Sin embargo, si un documento XML particular referencia uno o ms DTDs, hay una posibilidad de que dos o ms DTDs contengan el mismo nombre. Por lo tanto, el documento necesita especificar un espacio de nombres para cada DTD para que el analizador sepa qu definicin usar cuando analice un ejemplar de un DTD particular.

Aqu est la notacin estndard para declarar espacios de nombres XML, lo que normalmente se hace en el elemento raz de un documento XML. En el siguiente ejemplo de declaracin de espacios de nombres, la notacin xmlns identifica a nsName y se configura con la URL del espacio de nombres actual:

<priceList xmlns:nsName="myDTD.dtd"
    xmlns:otherNsName="myOtherDTD.dtd">
...
</priceList>

Dentro del documento, podemos especificar a qu espacio de nombres pertenece un elemento de esta forma:

<nsName:price> ...

Para hacer que nuestros analizador SAX o DOM pueda reconocer los espacios de nombres, llamamos al mtodo setNamespaceAware(true) sobre nuestro ejemplar de ParserFactory. Despus de esta llamada a este mtodo, cualquier parser que cree la factora de parsers tendr cuidado con los espacios de nombres.

.El API XSLT

XSLT (XSL Transformations), definido por el grupo de trabajo XSL de la W3C, describe un lenguaje para transformar documentos XML en otros documentos XML o en otros formatos. Para realizar la transformacin, normalmente necesitamos suministrar una hoja de estilo, que est escrita en "XML Stylesheet Language" (XSL). La hoja de estilo XSL especfica como se mostrarrn los datos XML. XSLT usa las instrucciones de formateo de la hoja de estilo para realizar la transformacin. El documento convertido puede ser otro documento XML o un documento en otro formato, como HTML.

JAXP soporta XSLT con el paquete javax.xml.transform, que nos permite enchufar un transformer XSLT para realizar las transformaciones. Los subpaquetes tienen APIs de streams espeficicos, de SAX-, y de DOM-, que nos permiten realizar transformaciones directamente desde rboles DOM y eventos SAX. Los dos siguientes ejemplos muestran como crear un documento XML desde un rbol DOM y como transfomar el documento XML resultante en HTML usando una hoja de estilo XSL.

.Transformiar un rbol DOM en un Documento XML

Para transformar el rbol DOM creado en la seccin anterior en un documento XML, el siguiente cdigo primero crea un objeto Transformer que realizar la transformacin:

TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();

Usando el nodo raz del rbol DOM, la siguiente lnea de cdigo construye un objeto DOMSource como fuente de la transformacin:

DOMSource source = new DOMSource(document);

El siguiente fragmento de cdigo crea un objeto StreamResult para tomar el resultado de la transformacin y transforma el rbol en XML:

File newXML = new File("newXML.xml");
FileOutputStream os = new FileOutputStream(newXML);
StreamResult result = new StreamResult(os);
transformer.transform(source, result);

.Transformar un Documento XML en un Documento HTML

Tambin podemos usar XSLT para convertir el nuevo documento XML, "newXML.xml", a HTML usando una hoja de estilo. Cuando escribimos una hoja de estilo usamos espacios de nombres XML para referenciar el XSL construido. Por ejemplo, cada hoja de estilo tiene un elemento raz identificando el lenguaje de la hoja de estilo, como se muestra en la siguiente lnea de cdigo:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

Cuando referenciamos un constructor particular en el lenguaje de la hoja de estilos, usamos el prefijo del espacio de nombres seguido por dos puntos y el constructor particular a aplicar. Por ejemplo, la siguiente parte de una hoja de estilo indica que el dato name debe insertase en una fila de una tabla HTML:

<xsl:template match="name">
    <tr><td>
        <xsl:apply-templates/>
    </td></tr>
</xsl:template>

La siguiente hoja de estilo especifica que el dato XML es convertido a HTML y que las entradas de cafs se insertan en las filas de una tabla:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="priceList">
        <html><head>Coffee Prices</head>
            <body>
                <table>
                    <xsl:apply-templates />
                </table>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="name">
        <tr><td>
            <xsl:apply-templates />
        </td></tr>
    </xsl:template>
    <xsl:template match="price">
        <tr><td>
            <xsl:apply-templates />
        </td></tr>
    </xsl:template>
</xsl:stylesheet>

Para realizar la transformacin necesitamos obtener un transformer XSLT y usarlo para aplicar la hoja de estilos a los datos XML. El siguiente fragmento de cdigo obtiene un transformer ejemplarizando un objeto TransformerFactory, lee los ficheros de la hoja de estilos y del XML, crea un fichero para la salida HTML, y finalmente obtiene el objeto Transformer desde la factora de objetos TransformerFactory llamada tFactory.

TransformerFactory tFactory = TransformerFactory.newInstance();
String stylesheet = "prices.xsl";
String sourceId = "newXML.xml";
File pricesHTML = new File("pricesHTML.html");
FileOutputStream os = new FileOutputStream(pricesHTML);
Transformer transformer = tFactory.newTransformer(new StreamSource(stylesheet));

La transformacin se consigue llamando al mtodo transform, pasndole los datos y el stream de salida:

transformer.transform(new StreamSource(sourceId), new StreamResult(os));

COMPARTE ESTE ARTÍCULO

ENVIAR A UN AMIGO
COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN GOOGLE +
ARTÍCULO ANTERIOR

SIGUIENTE ARTÍCULO

¡SÉ EL PRIMERO EN COMENTAR!
Conéctate o Regístrate para dejar tu comentario.