Parseando XML en Java mediante SAX

01Mar08

SAX es un API totalmente escrita en Java e incluida dentro del JRE que nos permite crear nuestro propio parser de XML.

Veremos como construir un parser genérico de XML y como lo podemos adaptar a nuestras necesidades.

Entre las clases más importantes a tener en cuenta tenemos:

Interface org.xml.sax.XMLReader:
Está interfaz que debe implementar un lector de XML.
Cada vez que el XMLReader encuentra el principio del archivo, el final, un elemento, un caracter especial, un espacio, etc. notifica esto al ContentHandler asociado.
Cada vez que encuentra un error se lo notifica al ErrorHandler asociado.

Interface org.xml.sax.ContentHandler:
La clase que la implementa obtiene la capacidad de recibir todas las notificaciones de contenido de un XMLReader.
La forma de asociar este a un XMLReader es mediante el método setContentHandler.

Interface org.xml.sax.ErrorHandler:
La clase que la implementa obtiene la capacidad de recibir todas las notificaciones de error producidas por un XMLReader
La forma de asociar este a un XMLReader es mediante el método setErrorHandler.
En caso de que no exista ningun ErrorHandler asociado al XMLReader, este ultimo no reportara ningun error, salvo las excepciones SAXParseException.

Clase org.xml.sax.helpers.DefaultHandler:
Clase que implementa tanto a ContentHandler como a ErrorHandler (además de DTDHandler y EntityResolver que no veremos por ahora), proveiendo implementaciones por defectos para todos sus métodos.

Esta clase es de la que extenderemos para poder crear nuestro propio parser de XML.

Clase org.xml.sax.helpers.XMLReaderFactory:
Clase que provee métodos estáticos para la creación de XMLReaders.
Utilizaremos el método estático XMLReaderFactory.createXMLReader() que nos devuelve el XMLReader un por defecto para nuestro sistema.

Creando el Lector
Para ello haremos de la siguiente forma:

class LectorXML extends DefaultHandler {

    private final XMLReader xr;

    public LectorXML() throws SAXException {
        xr = XMLReaderFactory.createXMLReader();
        xr.setContentHandler(this);
        xr.setErrorHandler(this);
    }
}

Hasta aquí hemos creado un clase LectorXML que hereda de DefaultHandler, donde en el constructor creamos el XMLReader mediante XMLReaderFactory.
Al XMLReader le asociamos el ContentHandler y ErrorHandler, que es el propio LectorXML. Agregamos un método para leer archivos XML:

class LectorXML extends DefaultHandler {

    private final XMLReader xr;

    public LectorXML() throws SAXException {
        xr = XMLReaderFactory.createXMLReader();
        xr.setContentHandler(this);
        xr.setErrorHandler(this);
    }

    public void leer(final String archivoXML)
             throws FileNotFoundException, IOException,
                       SAXException {
        FileReader fr = new FileReader(archivoXML);
        xr.parse(new InputSource(fr));
    }
}

En este punto estamos preparados para probar nuestro Lector:

public class PruebaSAX {
    public static void main(String[] args)
              throws FileNotFoundException, IOException,
                        SAXException {
        LectorXML lector = new LectorXML();
        lector.leer("test.xml");
    }
}

Si ejecutamos veremos que se produce nada (salvo que la ruta al XML sea incorrecta). Esto es porque los métodos de DefaultHandler tienen implementaciones vacías de los métodos.Sobrescribimos entonces algunos de los métodos para ver la salida:

class LectorXML extends DefaultHandler {

private final XMLReader xr;

public LectorXML() throws SAXException {
xr = XMLReaderFactory.createXMLReader();
xr.setContentHandler(this);
xr.setErrorHandler(this);
}

public void leer(final String archivoXML)
throws FileNotFoundException, IOException,
SAXException {
FileReader fr = new FileReader(archivoXML);
xr.parse(new InputSource(fr));
}

@Override
public void startDocument() {
System.out.println(“Comienzo del Documento XML”);
}

@Override
public void endDocument() {
System.out.println(“Final del Documento XML”);
}

@Override
public void startElement(String uri, String name,
String qName, Attributes atts) {
System.out.println(“tElemento: ” + name);

for (int i = 0; i < atts.getLength(); i++) { System.out.println("ttAtributo: " + atts.getLocalName(i) + " = "+ atts.getValue(i)); } } @Override public void endElement(String uri, String name, String qName) { System.out.println("tFin Elemento: " + name); } }[/sourcecode] Si ejecutamos ahora veremos como nos muestra el comienzo y fin del documento, así como todos los elementos y sus atributos de nuestro documento. De la misma forma podemos sobrescribir los métodos para ver los caracteres especiales que aparecen en el XML (espacios, saltos de lineas, etc), mostrar errores y excepciones generadas a la hora de realizar la lectura y parseo, etc. Espero que les sirva. Hasta la Próxima. Más Info



11 Responses to “Parseando XML en Java mediante SAX”

  1. 1 Alvaro Fernandez

    faltaria implementar el metodo characters para mostrar el valor del elemento, me ha sido muy util, muchas gracias !!

  2. 2 z.ciro

    Muy buena forma de presentar el codigo!! … pero una PREGUNTA!!! … que liberias debo importar y si son las org.*** donde las encuentro o descargo???? —

    Gracias!

  3. 3 Javi

    Muy buen post. De todo lo que he buscado sobre SAX, el que más útil me ha resultado.

    Gracias!

  4. 4 vanessa

    esto me servira para una expocision de sax.

  5. 5 joaquin

    a mi no me imprime los atributos, el .getLength() me marca como 0 y por eso no me imprime nada, a que se debe?

  6. 6 Francisco

    Muy buen aporte, gracias!!!!

  7. Grande, la idea q se ofrece es la ideal para empezar a trabajar con xml.
    La forma de presentarlo tambien merece elogio!

  8. 8 Aaron

    Me marca un error: NullPointException
    me dice que es nullo :S que pedo?

  9. 9 Herr

    Lo felicito; muy buen código !!

  10. 10 robfega

    Muy bueno el post. A mi también me fue útil este post: http://www.latascadexela.es/2008/07/java-y-xml-sax.html

  11. Gracias, me sirvio de mucho tu post… te lo aggradesco, por que ya me estaba volviendo loco.