martes, 29 de enero de 2013

Leer un XML con Sax

En este post vamos a mostrar como leer un fichero XML.

Una de las posibles formas es usando la librería SAX, que nos permitirá leer un XML sin tener que cargarlo entero en memoria y por consiguiente evitar posibles OutOfMemoryError. Otra posible forma sería leer el árbol DOM del XML pero es la menos recomendada y es más posible que se acabe el espacio en memoria al cargar todo el árbol DOM del XML en la misma. En mi caso he usado esta dependencia

 sax
 sax
 2.0.1

En nuestro ejemplo vamos a obtener la lista de libros del siguiente XML. Es un ejemplo básico:

 
  Las estrellas mi destino
  Alfred Bester
 
 
  El juego de Ender
  Orson Scott Card
 
 .....

En un primer paso creamos un parseador a través de la factoría de la que nos provee la propia SAX, a esta factoría le debemos pasar el fichero a parsear y el manejador que vamos a crear nosotros. En este manejador haremos el tratamiento necesario del XML para que nos devuelva los datos que queremos.
final SAXParserFactory spfac = SAXParserFactory.newInstance();
// Usamos la 'parser factory' para crear un objeto del tipo SAXParser
final SAXParser sp = spfac.newSAXParser();
// Creamos una instancia del manejador XML que hemos creado
final XMLOwnHandler handler = new XMLOwnHandler();
// Le indicamos al 'parser' cual va a ser el manejador encargado de 'parsear' el fichero e indicamos el fichero
sp.parse(fileName, handler);
// Devolvemos la lista de los objetos obtenidos en el XML, este metodo ya es propio del Handler y creado por nosotros
return handler.getList();
Creamos el manejador que debe de extender de DefaultHandler
public class XMLOwnHandler extends DefaultHandler {
El manejador creado por nosotros debe de implementar los métodos de DefaultHandler que necesitemos para realizar el tratamiento. En este ejemplo básico solo sobrescribiremos startElement, endElement y characters, pero el resto de métodos lo podéis ver aquí (http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html) En nuestro caso, el manejador devolvera una lista de Objetos libros que tiene el XML
private List list;
public List getList(){return list;}
También tenemos un par mas de atributos que nos ayudaran a construir la lista
private String characters;
private Libro libro;
Como hemos dicho, implementaremos solo los metodos startElement, endElement y characters. startElement Nos indica cual es el siguiente elemento del XML que se va a leer y nos permite leer sus atributos también.
public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) throws SAXException {
 //si es una etiqueta libro, creamos un nuevo objeto
 if ("libro".equals(qName)) {
  libro = new Libro();
  //iteramos por los atributos del elemento y recuperamos el valor de las paginas
  for (int i = 0; i < attributes.getLength(); i++) {
   if ("paginas".equals(attributes.getLocalName(i))) {
    libro.setPaginas(Integer.valueOf(attributes.getValue(i)));
   }
  }
 //Si es un elemento autor o nombre reiniciamos el valor del contenido
 } else if ("autor".equals(qName) || "nombre".equals(qName)) {
  characters = null;
 }
}
endElement nos indica cual es el elemento que se ha terminado de leer, esto nos indicara si hemos acabado de leer un elemento libro o el contenido de sus atributos.
public void endElement(final String uri, final String localName, final String qName) throws SAXException {
 //si se ha terminado de leer el elemento libro lo añadimos a la lista
 if ("libro".equals(qName)) {
  list.add(libro);
 //si se ha terminado de leer el contenido y es un autor lo almacenamos como tal
 } else if ("autor".equals(qName)) {
  libro.setAutor(characters);
 //si se ha terminado de leer el contenido y es un nombre lo almacenamos como tal
 } else if ("nombre".equals(qName)) {
  libro.setNombre(characters);
 }
}
characters nos permite leer el contenido de un elemento como nombre o autor.
public void characters(final char ch[], final int start, final int length) throws SAXException {
 //Almacenamos el contenido del elemento
 characters = new String(ch, start, length);
}
De esta forma podemos leer un archivo XML y todo su contenido. El método getList() nos devolverá una lista de POJOs Libro que contienen la información del XML y puede ser mejor tratada por nuestra aplicación.

No hay comentarios:

Publicar un comentario