Programación en castellano
Inicio > Tutoriales > Java y XML > APIs de Java para XML
-Tutoriales

APIs de Java para XML


El API JAXP

. Introducción

El API Java para Proceso de XML (JAXP) hace fácil el proceso de datos XML con aplicaciones escritas en el lenguaje Java. JAXP contiene los analizadores estándars 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 representación de objetos con ellos. La versión 1.1 de JAXP también soporta el estándar XSLT (XML Stylesheet Language Transformations), dándonos control sobre la representación de los datos y permitiéndonos convertir los datos a otros documentos XML o a otros formatos, como a HTML. JAXP también proporciona soporte para espacios de nombres, permitiéndonos trabajar con DTDs que de otra forma tendrían conflictos de nombrado.

Diseñado para ser flexible, JAXP nos permite usar cualquier analizador compatible XML desde dentro de nuestra aplicación. Esto lo hace con algo llamado capa de conectividad, que nos permite enchufar una implementación de los APIs SAX o DOM. La capa de conectividad también nos permite enchufar un procesador XSL, lo que nos permite controlar la forma en que se muestran los datos. La Implementación 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 Fundación 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 síntaxis de construcción, se lo notifica a la aplicación que lo está ejecutando. El analizador SAX notifica a la aplicación llamando a los métodos del interface ContentHandler. Por ejemplo, cuando el analizador encuentra un símbolo ("<"), llama al método startElement; cuando encuentra caracteres de datos, llama al método characters; y cuando encuentra un símbolo ("</"), llama al método endElement, etc. Para ilustrar, echemos un vistazo al documento XML del ejemplo de la primera sección y veamos que hace el analizador en cada línea. (Por simplicidad, no se han incluido las llamadas al método 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 métodos que llama el analizador no hacen nada, necesitamos escribir un subclase que implemente los métodos 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 implementación por defecto de ContentHandler) en la que escribiríamos nuestras propias implementaciones de los métodos startElement y characters.

Primero necesitamos crear un objeto SAXParser desde un objeto SAXParserFactory. Llamaríamos al método parse sobre él, pasándole la lista de precios y un ejemplar de nuestra nueva clase handler (con sus nuevas implementaciones de los métodos startElement y characters). En este ejemplo, la lista de precios es un fichero, pero el método parse también 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 método parse depende, por supuesto, de como estén implementados los métodos en handler. El analizador SAX atravesará el fichero priceList.xml línea a línea, llamando a los métodos apropiados. Además de los métodos ya mencionados, el analizador llamará a otros métodos como startDocument, endDocument, ignorableWhiteSpace, y processingInstructions, pero estos métodos también tienen sus implementaciones por defecto que no hacen nada.

Las siguientes definiciones de métodos muestran una forma de implementar los métodos 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 métodos trabajan juntos para buscar en el elemento name, los caracteres "Mocha Java", y el elemento price que sigue inmediantemente a "Mocha Java". Estos métodos usan tres banderas para seguir la pista de las condiciones que han encontrado. Observa que el analizador SAX tendrá que llamar a estos métodos más 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 después de la siguientes llamadas a métodos:

  • 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 validación 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 validación si fue crado mediante un objeto SAXParserFactory con la validación activada. Esto se hace para la factoría de objetos SAXParserFactory en la siguiente línea de código:

factory.setValidating(true);

Para que el analizador sepa qué DTD utilizar para la validación, el documento XML debe referenciar el DTD en su declaración DOCTYPE. Esa declaración debería 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 representación de objeto, en forma de árbol, de un documento XML analizado. Una vez que hemos construido el DOM, podemos manipularlo con métodos DOM como insert y remove, igual que manipularíamos 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, sólo podemos leer un documento XML, mientras que con un analizador DOM, podemos construir una representación objeto del documento y manipularlo en memoria, añadiendo un nuevo elemento o eliminando uno existente.

En el ejemplo anterior, usamos un analizador SAX para buscar sólo 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 búsquedas que implican unos pocos ítems, especialmente si el documento es largo. En el siguiente ejemplo, añadimos 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 sólo permite la lectuda de datos.

Supongamos que queremos añadir 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 código crea un objeto DocumentBuilderFactory, que luego es usado para crear el objeto DocumentBuilder. Luego el código llama al método parse sobre el builder, pasándole 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 representación DOM de la lista de precios situada en la memoria. El siguiente fragmento de código añade un nuevo café (con el nombre "Kona" y el precio de 13.50) al documento de la lista de precios. Como queremos añadir 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 través de la lista para encontrar "Mocha Java". Usando el interface Node incluido en el paquete org.w3c.DOM, el código crea un objeto Node para el nuevo elemento coffee y también nuevos nodos para los elementos name y price. Estos dos elementos contienen los datos, por eso el código crea un objeto TextNode para cada uno de ellos y añade 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 validación de la misa forma que un analizador SAX validante: llamamos a setValidating(true) sobre una factoría de analizadores DOM antes de usarla para crear nuestro analizador DOM, y nos aseguramos de que el documento XML referencia su DTD en la declaración 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 más DTDs, hay una posibilidad de que dos o más 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é definición usar cuando analice un ejemplar de un DTD particular.

Aquí está la notación estándard para declarar espacios de nombres XML, lo que normalmente se hace en el elemento raíz de un documento XML. En el siguiente ejemplo de declaración de espacios de nombres, la notación 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 método setNamespaceAware(true) sobre nuestro ejemplar de ParserFactory. Después de esta llamada a este método, cualquier parser que cree la factoría 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 transformación, normalmente necesitamos suministrar una hoja de estilo, que está escrita en "XML Stylesheet Language" (XSL). La hoja de estilo XSL específica como se mostrarrán los datos XML. XSLT usa las instrucciones de formateo de la hoja de estilo para realizar la transformación. 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 sección anterior en un documento XML, el siguiente código primero crea un objeto Transformer que realizará la transformación:

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

Usando el nodo raíz del árbol DOM, la siguiente línea de código construye un objeto DOMSource como fuente de la transformación:

DOMSource source = new DOMSource(document);

El siguiente fragmento de código crea un objeto StreamResult para tomar el resultado de la transformación 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

También 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 raíz identificando el lenguaje de la hoja de estilo, como se muestra en la siguiente línea de código:

<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 cafés 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 transformación necesitamos obtener un transformer XSLT y usarlo para aplicar la hoja de estilos a los datos XML. El siguiente fragmento de código 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 factoría 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 transformación se consigue llamando al método transform, pasándole los datos y el stream de salida:

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

Copyright © 1999-2007 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network

red internet: musica mp3 | logos y melodias | hospedaje web linux | registro de dominios | servidores dedicados
más internet: comprar | recursos gratis | posicionamiento en buscadores | tienda virtual | gifs animados