El API JAXP

En esta secci�n del tutorial, construiremos un "Document Object Model" (DOM) ley�ndolo desde un fichero XML existente. Luego lo escribiremos como XML para verificar que el programa est� funcionando.

.�Leer un Documento XML dentro de un DOM

El DOM proporciona los APIs que nos permiten crear nodos, modificarlos, borrarlos y redistribuirlos. Por eso, es relativamente f�cil crear un DOM, como veremos en Crear y Manipular un DOM.

Sin embargo, la Especificaci�n Nivel 1 DOM es silenciosa con respecto a c�mo realizar la entrada y la salida. Nos dice c�mo tiene que operar un DOM, pero no cubre los m�todos para leer o escribir XML. Como resultado, no podemos crear un DOM desde un fichero XML existente sin salirnos de la especificaci�n Nivel 1 de DOM.

El interface DocumentBuilder de JAXP estandariza la soluci�n a este problema especificando una variedad de m�todos analizadores que toman un objeto File o un stream de entrada, o un objeto InputSource de SAX, o una URI. Cuando invocamos a uno de estos m�todos, una implementaci�n de DocumentBuilder devuelve un objeto org.w3c.dom.Document.

Nota:

Para hacer la salida de DOM, utilizaremos una caracter�stica de la implementaci�n de referencia. Los analizadores de diferentes fabricantes podr�an usar otros mecanismos para conseguir el objetivo.

.�Crear el Esqueleto

Ahora que hemos visto una r�pida introducci�n de c�mo crear un DOM, construyamos un sencillo programa que lea un documento XML en un DOM y luego lo escribamos de vuelta de nuevo.

Nota:

El c�digo explicado en esta secci�n est� en DomEcho01.java. Los ficheros sobre los que opera son slideSample01.xml y slideSample10.xml. La salida est� en DomEcho01-01.log y DomEcho01-10.log. El fichero slideSample10.xml referencia a slideshow3.dtd que, a su vez, referencia a un (muy sencillo) xhtml.dtd.

Empezamos con una l�gica b�sica normal para una aplicaci�n, y chequeamos para asegurarnos que se le ha suministrado un argumento en la l�nea de comandos:

public class DomEcho {
    public static void main (String argv [])
    {
        if (argv.length != 1) {
            System.err.println ("Usage: java DomEcho filename");
            System.exit (1);
        }
    }// main

}// DomEcho

.�Importar las Clases Necesarias

En esta secci�n vamos a ver todas las clases nombradas individualmente. Es decir que podremos ver de d�nde viene cada clase que queremos referenciar en la documentaci�n del API. En nuestra propia aplicaci�n, tambi�n podr�amos querer reemplazar las sentencias importantes, como las de abajo, con la forma corta: javax.xml.parsers.*.

A�adimos estas l�neas para importar los APIs JAXP que vamos a usar:

import javax.xml.parsers.DocumentBuilderFactory;  
import javax.xml.parsers.FactoryConfigurationError;  
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.DocumentBuilder;

A�adimos estas l�neas para las excepciones que pueden lanzarse cuando se analiza un documento XML:

import org.xml.sax.SAXException;  
import org.xml.sax.SAXParseException;

A�adimos estas l�neas para leer un fichero XML de ejemplo e identificar errores:

import java.io.File;
import java.io.IOException;

Finalmente, importamos la defici�n del W3C para un DOM y sus excepciones:

import org.w3c.dom.Document;
import org.w3c.dom.DOMException;
Nota:

Las DOMExceptions s�lo se lanzan cuando atraviesan o manipulan un DOM. Los errores que ocurren durante el an�lisis o reporte usando un mecanismo diferente que este se cubren abajo.

.�Declarar el DOM

La clase org.w3c.dom.Document es el nombre W3C para un DOM. Siempre que analizemos o creemos un documento XML, resultar� un Document. Queremos referenciar este objeto desde otro m�todo m�s tarde en este tutorial, por eso lo definimos como un objeto global:

public class DomEcho
{    
    static Document document;

    public static void main (String argv [])
    {

Necesita ser static, porque vamos a generar su contenido desde el m�todo main dentro de unos minutos.

.�Manejar Erorres

Luego, entramos en la l�gica de manejo de errores. Esta es la misma l�gica que vimos en Manejar Errores en el tutorial de SAX, por eso no entraremos en detalles ahora. El �nico punto que merece la pena observar es que un constructor de documentos conforme el JAXP es necesario que reporte excepciones SAX cuando tiene un problema analizando un documento XML. El analizador DOM no tiene que usar realmente un analizador SAX internamente, pero como el est�ndard SAX estaba realmente aqu�, parec�a tener sentido usarlo para reportar errores. Como resultado, el c�digo de manejo de errores para aplicaciones DOM y SAX es bastante similar.

public static void main (String argv [])
{
    if (argv.length != 1) {
        ...
    }

    try {
    } catch (SAXParseException spe) {
       // Error generated by the parser
       System.out.println ("\n** Parsing error" 
          + ", line " + spe.getLineNumber ()
          + ", uri " + spe.getSystemId ());
       System.out.println("   " + spe.getMessage() );
       // Use the contained exception, if any
       Exception  x = spe;
       if (spe.getException() != null)
           x = spe.getException();
       x.printStackTrace();
    } catch (SAXException sxe) {
       // Error generated by this application
       // (or a parser-initialization error)
       Exception  x = sxe;
       if (sxe.getException() != null)
           x = sxe.getException();
       x.printStackTrace();

    } catch (ParserConfigurationException pce) {
       // Parser with specified options can't be built
       pce.printStackTrace();
    } catch (IOException ioe) {
       // I/O error
       ioe.printStackTrace();
    }
}// main 

.�Ejemplarizar la Factor�a

Luego a�adimos el c�digo en negrita de abajo para obtener un ejemplar de una factor�a que nos puede ofrecer un constructor de documentos:

public static void main (String argv [])
{
    if (argv.length != 1) {
        ...
    }
    DocumentBuilderFactory factory = 
		DocumentBuilderFactory.newInstance();
    try {

.�Obtener un Analizador y Analizar el Fichero

Ahora, a�adimos el c�digo en negrita de abajo para obtener un ejemplar de un analizador, y lo usamos para analizar el fichero especificado:

try {
   DocumentBuilder builder = factory.newDocumentBuilder();
   document = builder.parse( new File(argv[0]) );
} catch (SAXParseException spe) {

.�Escribir el XML

En este punto, el c�digo tiene la habilidad de leer y analizar un documento XML. Para escribir el documento para su inspecci�n, necesitamos un paso fuera del est�ndard del nivel 1 de DOM que crea la secci�n DOM del JAXP. Las operaciones de escritura de DOM no se especificaron hasta el nivel 3 de DOM. Para obtenerlas mientras tanto, forzamos el objeto Document devuelto por DocumentBuilder al objeto real que la implementaci�n de referencia devuelve: XmlDocument.

Nota:

Este material es espec�fico de Project X, la implementaci�n de referencia de Sun. El material de esta secci�n no forma parte del est�ndard. En su lugar, representa funcionalidades �tiles que podr�amos necesitar para aprovecharnos hasta que se haya estandarizado alg�n mecanismo equivalente. Como no forma parte del est�ndard JAXP, las funcionalidades descritas aqu� podr�an muy bien no existir en otros analizadores est�ndards JAXP.

.�Usar XmlDocument

Empezamos a�adiendo las sentencias import que definen la clase:

import org.w3c.dom.Document;
import org.w3c.dom.DOMException;

import com.sun.xml.tree.XmlDocument;

public class DomEcho
{  

El prefijo com.sun. de esta clase es nuestra advertencia del hecho de que nos estamos moviendo fuera del est�ndard JAXP, y haciendo uso de una caracter�stica de la implementaci�n de referencia de Sun.

Luego, a�adimos el c�digo en negrita de abajo para forzar el objeto Document a XmlDocument y escribirlo:

try {
  DocumentBuilder builder = factory.newDocumentBuilder();
  document = builder.parse( new File(argv[0]) ); 
           
  XmlDocument xdoc = (XmlDocument) document;
  xdoc.write (System.out);

} catch (SAXParseException spe) {

.�Ejecutar el Programa

A trav�s del tutorial DOM, usaremos el ejemplo de diapositivas creado en la secci�n SAX. En particular, usaremos slideSample01.xml, un sencillo fichero XML sin mucho dentro, y slideSample10.xml, un ejemplo m�s complejo que incluye un DTD, instrucciones de procesamiento, referencias a entidades, y una secci�n CDATA.

Para las instrucciones de c�mo compilar y ejecutar nuestro programa, puedes ver Compilar el Programa y Ejecutar el Programa, del tutorial de SAX. Sustituimos "Echo" por "DomEcho" como el nombre del programa, y ya estamos listos. Cuando ejecutemos el programa sobre slideSample01.xml, �sta es la salida que veremos:

<?xml version="1.0" encoding="UTF-8"?>

<!--  A SAMPLE set of slides  -->
<slideshow title="Sample Slide Show" date="Date of publication" 
	author="Yours Truly">

    <!-- TITLE SLIDE -->
    
  <slide type="all">
      
    <title>Wake up to WonderWidgets!</title>
    
  </slide>

    
  <!-- OVERVIEW -->
    
  <slide type="all">
      
    <title>Overview</title>
      
    <itdestacar>Why 
      <destacar>WonderWidgets</destacar> are great
    </itdestacar>
      
    <item />
      
    <itdestacar>Who 
      <destacar>buys</destacar> WonderWidgets
    </itdestacar>
    
  </slide>


</slideshow>

Cuando ejecutamos el programa sobre slideSample10.xml, el resultado es muy similar. En particular, observamos que la referencia de entidad permanece igual que como fue escrita originalmente (no es reemplazada con el texto de la entidad):

<itdestacar>
 &copyright;
</itdestacar>

Tambi�n, observa que la secci�n CDATA se ha preservado:

   <itdestacar>
      <![CDATA[Diagram.                         
    frobmorten <------------ fuznaten
        |            <3>        ^
        | <1>                   |   <1> = fozzle
        V                       |   <2> = framboze    
      staten--------------------+   <3> = frenzle
                     <2>
      ]]>
    </itdestacar>

.�Informaci�n Adicional

Ahora que hemos le�do con �xito un DOM, hay una o dos cosas m�s que necesitamos saber para poder usar DocumentBuilder de forma efectiva.

  • Configurar la Factor�a
  • Manejar Errores de Validaci�n

.�Configurar la Factor�a

Por defecto, la factor�a devuelve un analizador sin validaci�n que no sabe nada sobre espacios de nombres. Para obtener un analizador con validaci�n, y/o uno que entienda de espacios de nombres, configuramos la factor�a para seleccionar cualquiera de estas opciones usando los comandos en negrita de abajo:

public static void main (String argv [])
{
    if (argv.length != 1) {
        ...
    }
    DocumentBuilderFactory factory = 
	DocumentBuilderFactory.newInstance();
    factory.setValidating(true);
    factory.setNamespaceAware(true);
    try {
            ...
Nota:

No es necesario que los analizadores conformes con JAXP soporten todas las combinaciones de estas opciones, incluso aunque el analizador de referencia lo haga. Si especificamos una combinaci�n de opciones inv�lida, la factor�a generar� una ParserConfigurationException cuando intentemos obtener un ejemplar del analizador.

Aprenderemos m�s sobre c�mo usar los espacios de nombres en la �ltima p�gina del tutorial DOM, Usar Espacios de Nombres. Para completar esta secci�n, queremos aprender algo sobre...

.�Manejar Errores de Validaci�n

Recuerda que la respuesta por defecto a un error de validaci�n, seg�n lo dictado por el est�ndard, es no hacer nada. El est�ndard JAXP requiere que se lancen excepciones SAX, por eso usamos exactamente el mismo mecanismo de manejo de errores que usamos en la aplicaci�n SAX. En particular, necesitamos usar el m�todo setErrorHandler de DocumentBuilder para suminstrarle un objeto que implemente el interface ErrorHandler de SAX.

Nota:

DocumentBuilder tambi�n tiene un m�todo setEntityResolver que podemos usar.

El c�digo de abajo usa un adaptador de clase interna an�nimo para proporcionar este ErrorHandler. El c�digo en negrita es la parte que se asegura de que los errores de validaci�n generen una excepci�n:

builder.setErrorHandler(
  new org.xml.sax.ErrorHandler() {
      // ignore fatal errors (an exception is guaranteed)
      public void fatalError(SAXParseException exception)
      throws SAXException {
      }

      // treat validation errors as fatal
      public void error (SAXParseException e)
      throws SAXParseException
      {
        throw e;
      }

      // dump warnings too
      public void warning (SAXParseException err)
      throws SAXParseException
      {
        System.out.println ("** Warning"
           + ", line " + err.getLineNumber ()
           + ", uri " + err.getSystemId ());
        System.out.println("   " + err.getMessage ());
      }
  }
); 

Este c�digo usa una clase interna an�nima para generar un ejemplar de un objeto que implementa el interface ErrorHandler. Como no tiene nombre de clase, es "an�nima". Podemos pensar en ella como un ejemplar de "ErrorHandler", aunque t�cnicamente es un ejemplar sin nombre que implementa el interface especificado. El c�digo es sustancialmente el mismo que el descrito en la secci�n Manejo de Errores del tutorial SAX.

Nota:

Las clases internas se soportan desde la versi�n 1.2 de la plataforma Java. Si est�mos codificando para la versi�n 1.1, crearemos una clase externa que implemente ErrorHandler.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR

SIGUIENTE ARTÍCULO