Generar una Estructura de Datos Arbitraria
En la última página, vimos cómo nuestro conocimiento del análisis de SAX era muy útil
cuando teníamos errores del analizador. En esta sección, usaremos este conocimiento para
simplificar los procesos para convertir un estructura de datos arbitraria en XML.
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.
|
¿Cómo Funciona?
Recordamos de La Implementación de Referencia
"Project X" que la implementación de referencia de Sun para el API JAXP usa un
analizador SAX para leer los datos XML cuando se construye un DOM. En esta sección, veremos
cómo aprovecharnos de este echo para convertir un conjunto de datos existentes en XML.
En genaral, vamos a ir a:
- Modificar un programa que lee datos y los modifica para generar eventos SAX.
- Con el analizador SAX a mano, conectaremos con un constructor de documento para crear un DOM.
- Usaremos el método write de la implementación de referencia
para producir XML.
Hemos asumido que tenemos algún programa que puede leer los datos. Asumiendo que tenemos un
conjunto de datos que queremos convertir, es bueno tener alguna aplicación que pueda leerlos.
El Analizador empieza en este punto.
Modificar el "Analizador" para Generar Eventos SAX
El siguiente paso es modificar el analizador para generar eventos SAX. Empezamos
extendiendo javax.xml.parsers.SAXParser.
Generar un evento SAX significa invocar a uno de los métodos de
org.xml.sax.DocumentHandler. Vimos muchos de estos métodos
en Mostrar un Fichero XML con el Analizador SAX
y Añadir Manejadores de Eventos Adicionales.
Aquí tenemos el mínimo conjunto de eventos que el analizador necesita generar para algunos
DocumentHandler, d:
d.startDocument()
d.endDocument()
d.startElement(String name, AttributeList attrs)
d.endElement(String name)
d.characters(char buf [], int offset, int len)
|
Nota:
Como cada uno de estos métodos puede lanzar una SAXException,
el analizador tendrá que estar preparado para manejarlas.
|
Aquí están los eventos DocumentHandler que normalmente queremos ignorar:
setDocumentLocator(Locator l)
ignorableWhitespace(char buf [], int offset, int len)
processingInstruction(String target, String data)
El fichero de datos no tiene que procesar las instrucciones, por eso es fácil ver porque
ignoramos éste. Y ignorableWhitespace genera exactamente el
mismo XML que la antigua llamada a characters, por eso éste también
puede ser ignorado. Lo que nos deja setDocumentLocator.
El evento setDocumentLocator es sólo útil para una aplicación que vaya
a interpretar los datos en un fichero XML, identificar un nombre de fichero relativo a la
localización actual, y recuperar este fichero. Pero los eventos generados por nuestro
analizador no tienen nada que ver con dicho proceso -- ellos van a un
DocumentHandler, que construirá un árbol DOM usando nuestros datos.
Implementar el Interface org.xml.sax.Parser
Una vez que el analizador puede generar eventos SAX, necesita poder decirle dónde enviarlos.
Para hacer esto, debe implementar el interface org.xml.sax.Parser y,
como mínimo definir el método setDocumentHandler() con un implementación
no nula.
Aquí tenemos una lista de los métodos de este interface. Podríamos elegir proporcionar
implementaciones nulas para muchos de ellos, pero podríamos elegir implementar algunas, como
setErrorHandler, en el interés de crear una aplicación más robusta.
parse(InputSource source)
parse(java.lang.String systemId)
setDocumentHandler(DocumentHandler handler)
setDTDHandler(DTDHandler handler)
setEntityResolver(EntityResolver resolver)
setErrorHandler(ErrorHandler handler)
setLocale(java.util.Locale locale)
Conectar nuestro Analizador a un XmlDocumentBuilder
Luego usamos el código de abajo para conectar nuestro analizador SAX con un constructor
de documentos, y procedemos a analizar los datos. (El código en negrita muestra las partes
específicas de Sun).
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import org.xml.sax.Parser;
import com.sun.xml.parser.Resolver;
import javax.xml.parsers.DocumentBuilder;
import com.sun.xml.tree.XmlDocumentBuilder;
import com.sun.xml.tree.XmlDocument;
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
Parser parser = saxParser.getParser();
builder = new XmlDocumentBuilder();
builder.setIgnoringLexicalInfo(true); // Skip comments, entity refs, etc.
parser.setDocumentHandler(builder);
parser.parse(Resolver.createInputSource(new File(argv[0])));
XmlDocument document = builder.getDocument();
En este código, obtenemos un ejemplar de nuestra factoría de analizadores SAX, usamos esto
para obtener nuestro analizador, y luego creamos un ejemplar del
XmlDocumentBuilder de la implementación de referencia. Esta clase
implementa el interface DocumentHandler, que nos permite conectarlo a
nuestro analizador.
Luego invocamos al método parse del analizador, asumiendo que lo hemos
implementado, o cualquier método que lo dispare. Como analiza lo datos, también genera eventos
SAX. El XmlDocumentBuilder reacciona a dichos eventos y construye un DOM
en el proceso. Recuperamos este DOM con el método getDocument,
especificando el nombre de la clase (XmlDocument) en vez del interface general (Document) por
eso podemos utilizar los métodos de salida de XmlDocument.
Escribir la Salida
Como el último paso de nuestro programa, escribimos el DOM como un documento XML usando el
método write de XmlDocument que aprendimos en la
página anterior.
Ejecutarlo
Finalmente, especificamos el path completo de nuestra factoria de analizadores en la línea
de comandos como una propiedad del sistema, usando la bandera -D, de esta forma:
-Djavax.xml.parsers.SAXParserFactory=fully.qualified.name.of.parserFactory
Ahora, ejecutamos la aplicación. ¡Felicidades! hemos convertido con éxito una estructura de
datos en XML con un esfuerzo mínimo. Bien, ok. Fue un gran esfuerzo, pero lo hicimos!