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
*
*

*/

1 comentario:

Antonio dijo...

Buenos días

Llevo un par de días "trabajando" con tu código puesto que estoy intentando validar un fichero XML con varios DTD.

Por más vueltas que le doy al asunto no consigo descubrir como funciona puesto que no se si recoge mis DTD y si se valida respecto a la estructura de mis DTD o no pq si le quito una etiqueta si que me muestra un error pero si le meto un atributo "prohibido" en una de las etiquetas no me muestra nada de nada.

Te dejo mi correo antonio_ruiz_cebrian@yahoo.es por si me quieres escribir.

Gracias por adelntado.

Saludos