Búsqueda personalizada

jueves, 23 de abril de 2009

Ejemplo Java, XML y SAX

package samples.xml.sax;

//paquetes de JAXP para usar SAX
import org.xml.sax.*;
import org.xml.sax.helpers.*;

import java.util.*;
import java.io.*;

public class SAXLocalNameCount extends DefaultHandler {

/** Un Hashtable con los nombres de los Tags como llaves y "Integers" como valores */
private Hashtable tags;

// Sobreescribimos el metodo startDocument, esto ejecuta la primera accion que
//se realiza al momento de parsear el documento

public void startDocument() throws SAXException {
tags = new Hashtable();
}


//Sobreescribimos el metodo startElement el cual ocurre cada ves que al parsear
//el documento se encuentra un nuevo elemento.
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts)
throws SAXException//SAXException es la excepcion que nos manda cuando ocurre algun error al momento
{ //De parsear el documento usando SAX.
//LocaName es el nombre del elemento(la etiqueta(tag))
String key = localName;
//Guardamo el valor del tag en un objeto
Object value = tags.get(key);

//Si el valor del tag en el HashTable es null(es la primera vez que se usa ese objeto por lo tanto no hemos guardado con anterioridad ese tag y su valor es nulo) se le pone el valor de 1
if (value == null) {
// Agregamos una nueva entrada al HashTag con elnombre del tag como llaves y 1 como valor
tags.put(key, new Integer(1));
} else {
// Si en el Hashtable ya existia un valor para cierta llave("tan") entonces aumentamos ese valor en uno
int count = ((Integer)value).intValue();
count++;
tags.put(key, new Integer(count));
}
}

// Parser calls this once after parsing a document
//Sobreercribimoel mrtodo endDocument() el cual ejecuta una accion un instante antes de terminar el parseo.
public void endDocument() throws SAXException {
Enumeration e = tags.keys();
while (e.hasMoreElements()) {
String tag = (String)e.nextElement();
int count = ((Integer)tags.get(tag)).intValue();
//imprimimos el numero de ocurrencias de cada tag(el nombre lo obtenemos por que es el mismo nombre de la llave y el valor es el que contiene el HashTable en ese lugar)

System.out.println("Local Name \"" + tag + "\" occurs " + count
+ " times");
}
}


//Sobreescribimos el meto characters este metodo sirve para leer cada cadena de caracteres que
//encuentra al hacer el pars contiene tres parametros ch - los caractetres del documneto XML
// start - la posición inicial del arreglo y length - l numero de caracteres en el arreglo
@Override
public void characters(char[] ch, int start, int length)
throws SAXException
{
//imprimimos todos los caracteres del arreglo
System.out.println( new String(ch,start,length));
}

/**
* Metodo para convertir un archivo en un url.
*/
private static String convertToFileURL(String filename) {
// Pdemos hacer esto de una forma mas facil a partir de java 1.2 con:
// "path = file.toURL().toString()".
String path = new File(filename).getAbsolutePath();
if (File.separatorChar != '/') {
path = path.replace(File.separatorChar, '/');
}
if (!path.startsWith("/")) {
path = "/" + path;
}
return "file:" + path;
}

private static void usage() {
System.err.println("Usage: SAXLocalNameCount [-options] ");
System.err.println(" -dtd = DTD validation");
System.err.println(" -usage or -help = this message");
System.exit(1);
}


//Clase main
static public void main(String[] args) throws Exception {

//nombre del archivo
String filename = null;
//validación DDT
boolean dtdValidate = false;
String schemaSource = null;

// Verificamos si el main tiene argumentos argumentos(si existen) esto nos servirá despues para ver si validamos el DTD,
//Pr cuestioenes de espacio no especificaremso estos, pero tenemos que saber que aunque en tes momento nos marca un error si
//tratamos de invocar los parametros -usage o -help es por que en este momento no se tiene planeado usarlos
//pero es una buena tecnica, mandar un mensaje de eero para que en caso de que alguien mas desee usarlos, sepa
//que tiene que sobreescribir este metodo, y como ya esta pseudoimplementado no tendra que rehacer todo el codigo, solo
//sobreescribir el metodo usage()
for (int i = 0; i < args.length; i++) {
if (args[i].equals("-dtd")) {
dtdValidate = true;
} else if (args[i].equals("-usage")) {
usage();
} else if (args[i].equals("-help")) {
usage();
} else {
filename = args[i];

// Must be last arg
if (i != args.length - 1) {
usage();
}
}
}
if (filename == null) {
usage();
}

// Creamos un Objeto XMLReader
XMLReader xmlReader = XMLReaderFactory.createXMLReader();

// Ponemos el conten handler ContentHandler del XMLReader
xmlReader.setContentHandler(new SAXLocalNameCount());

// Agregamos un manejador de errores despues del parseo
xmlReader.setErrorHandler(new MyErrorHandler(System.err));

// LE decimos al XMLReader que inicie el parseo del documento.
xmlReader.parse(convertToFileURL(filename));
}

// Error handler to report errors and warnings
//Creaos un manejador de errores propio implementando la interfaz ErrorHandler
// y obiamente sobreescribiendo sus metosos
private static class MyErrorHandler implements ErrorHandler {
/** Error handler output goes here */
private PrintStream out;

MyErrorHandler(PrintStream out) {
this.out = out;
}

/**
* Regresa un String con los detalles del la excepcion mandada por el parser
*/
private String getParseExceptionInfo(SAXParseException spe) {
String systemId = spe.getSystemId();
if (systemId == null) {
systemId = "null";
}
String info = "URI=" + systemId +
" Line=" + spe.getLineNumber() +
": " + spe.getMessage();
return info;
}

// Los siguentes metodos son propios el la interfas de SAX: ErrorHandler.

public void warning(SAXParseException spe) throws SAXException {
out.println("Warning: " + getParseExceptionInfo(spe));
}

public void error(SAXParseException spe) throws SAXException {
String message = "Error: " + getParseExceptionInfo(spe);
throw new SAXException(message);
}

public void fatalError(SAXParseException spe) throws SAXException {
String message = "Fatal Error: " + getParseExceptionInfo(spe);
throw new SAXException(message);
}
}
}


/*
* Como podemos ver para hacer un parseo a XML usando SAX, tenemos que ir
* obteniendo los datos con diversos metodos al momento de estar parseando el
* documento, esta es una de las principales ventas y desventas de SAX, ventaja
* por que no tenemos que cargar todo el documento en memoria, eso hace que
* sea mucho mas rapido y mas eficiente, desventaja, por que complica mucho el
* modo de obtener los datos, ya que a fierta tenemos que "atraparlos" al momento
* de hacer el parseo.
*
* Para mas información de los metodos que se pueden sobreescribir al momento
* pueden verlo en
http://java.sun.com/j2se/1.4.2/docs/api/org/xml/sax/package-tree.html
* pero en especial verifiquen los metodos del manejador de Contenido
* http://java.sun.com/j2se/1.4.2/docs/api/org/xml/sax/ContentHandler.html
*
* y el manejador de errores
* http://java.sun.com/j2se/1.4.2/docs/api/org/xml/sax/ErrorHandler.html
*
*

*/