Un ejemplo de lectura SAX con DTD

Ramiro Lago (Enero 2007)

Analizador

La lógica de SAX se basa en paradigma ya utilizado en Swing: programación orientada a eventos. El analizador va recibiendo una serie de eventos (retrollamadas), al estilo de los listener de AWT y Swing, a medida que va leyendo las etiquetas. Un ejemlplo:


import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

/***************************************************************************
* Manejador de eventos SAX
***************************************************************************/
public class Manejador extends DefaultHandler {
 
    public void setDocumentLocator(Locator loc) {
    }
    public void startDocument() {
    }
    public void endDocument() {
    }
    public void processingInstruction(String destino, String datos) {
    }
    public void startPrefixMapping(String prefijo, String uri) {
    }
    public void endPrefixMapping(String prefijo) {
    }
    public void startElement(String espacioNombres, String nomLocal, String nomCompleto, Attributes atrs) {
		System.out.println("Nombre local:" + nomLocal + " Nombre completo:" + nomCompleto );
		for ( int i = 0; i < atrs.getLength(); i++) {
			System.out.println("    ATRIB. Nombre local: " + atrs.getLocalName(i) );	
			System.out.println("    ATRIB. Tipo:         " + atrs.getType(i) );	
			System.out.println("    ATRIB. Valor:        " + atrs.getValue(i) );	
		}		
    }
    public void endElement(String espacio, String nomLocal, String nomCompleto) {
    }
    public void characters(char[] ch, int inicio, int longitud) {
		String cad = new String( ch, inicio, longitud);
		System.out.println("    Caracteres: " + cad );
		System.out.println("         Inicio:" + inicio + " Longitud:" + longitud );	
    }
    public void ignorableWhitespace(char[] ch, int comienzo, int fin) {
    }
    public void skippedEntity(String nombre) {
    }
    public void error(SAXParseException exc) throws SAXException {      
		mostrarError( exc, "Se encontró un error");
    }
    public void fatalError(SAXParseException exc) throws SAXException { 
		mostrarError( exc, "Se encontró un error fatal");
    }
    public void mostrarError( SAXParseException exc, String aviso )  throws SAXException {
		System.out.println( aviso + ".  Línea:    " + exc.getLineNumber() );
		System.out.println( "URI:     " + exc.getSystemId() );
		System.out.println( "Mensaje: " + exc.getMessage() );
		throw new SAXException(aviso);// 
    }
}

Los métodos más utilizados:

En este ejemplo desde el método main() iniciamos el análisis SAX:


import java.io.File;
import java.io.IOException;
import org.xml.sax.*;
import javax.xml.parsers.*;

/***************************************************************************
* Ejemplo de análisis XML con SAX
* Usamos DTD
***************************************************************************/
public class Inicio {

	public static void main(String[] args) {
		String nomArchivo = "/src/xmlSAX01/libreria3.xml";
		try {
			
			//// Directorio actual
			File dirActual = new File(".");			
			System.out.println("El directorio actual es " + dirActual.getCanonicalPath());
			
			//// Abro archivo XML tomando una referencia relativa al directorio actual
			System.out.println("Trato de abrir el archivo " + dirActual.getCanonicalPath() + nomArchivo );
			File fich = new File(dirActual.getCanonicalPath() + nomArchivo );
			if ( fich.exists() )
				System.out.println("Se ha abierto el archivo. Inicio del análisis" );
			else {
				System.out.println("No se ha abierto el archivo " + fich.getAbsolutePath());
				return;				
			}
			
			//// Creo y configuro una factoria
			SAXParserFactory factoria = SAXParserFactory.newInstance();
			factoria.setNamespaceAware(true);	// Soporta espacio de nombres XML
			factoria.setValidating(true);		// Valida documento

			//// Análisis
			SAXParser parser= factoria.newSAXParser();
			Manejador man = new Manejador();
			parser.parse( fich, man );		// Parser del fichero 'fich' con el manejador 'man'
			System.out.println("Fin del análisis.");
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (SAXException e) {
			e.printStackTrace();
		}
		catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		catch (Exception e) {
			e.printStackTrace();
		}		
	}
}

Los documentos

El archivo DTD (libreria3.dtd), que especifica la estructura de datos, es el siguiente:


<?xml version="1.0" encoding="UTF-8" ?>
<!ELEMENT libreria3 ( libro+ ) >
<!ELEMENT libro (autor*, titulo, precio,rebaja?,resumen?)>
<!ELEMENT autor ( #PCDATA ) >
<!ELEMENT titulo ( #PCDATA ) >
<!ELEMENT precio ( #PCDATA ) >
<!ELEMENT rebaja ( #PCDATA ) >
<!ELEMENT resumen (#PCDATA ) >
<!ATTLIST resumen
	autor CDATA #IMPLIED
	fichero CDATA #REQUIRED
>

El archivo XML hace referencia al DTD:


<?xml  version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE libreria3 SYSTEM "libreria3.dtd">

<libreria3>
<libro>
	<autor>Miguel De Cervantes</autor>
	<titulo>El Quijote</titulo>
	<precio>18</precio>
</libro>
<libro>
	<autor>Antonio Lopez</autor>
	<autor>Ana Perez</autor>
	<titulo>Cómo crecer</titulo>
	<precio>25</precio>
	<rebaja>10%</rebaja>
	<resumen fichero="ert34.doc" />
</libro>
</libreria3>

Ejemplo de ejecución


El directorio actual es C:\DOC\Java_eclipse\docenBasico
Trato de abrir el archivo C:\DOC\Java_eclipse\docenBasico/src/xmlSAX01/libreria3.xml
Se ha abierto el archivo. Inicio del análisis
Nombre local:libreria3 Nombre completo:libreria3
Nombre local:libro Nombre completo:libro
Nombre local:autor Nombre completo:autor
    Caracteres: Miguel De Cervantes
         Inicio:79 Longitud:19
Nombre local:titulo Nombre completo:titulo
    Caracteres: El Quijote
         Inicio:117 Longitud:10
Nombre local:precio Nombre completo:precio
    Caracteres: 18
         Inicio:147 Longitud:2
Nombre local:libro Nombre completo:libro
Nombre local:autor Nombre completo:autor
    Caracteres: Antonio Lopez
         Inicio:187 Longitud:13
Nombre local:autor Nombre completo:autor
    Caracteres: Ana Perez
         Inicio:218 Longitud:9
Nombre local:titulo Nombre completo:titulo
    Caracteres: Cómo crecer
         Inicio:246 Longitud:11
Nombre local:precio Nombre completo:precio
    Caracteres: 25
         Inicio:277 Longitud:2
Nombre local:rebaja Nombre completo:rebaja
    Caracteres: 10%
         Inicio:299 Longitud:3
Nombre local:resumen Nombre completo:resumen
    ATRIB. Nombre local: fichero
    ATRIB. Tipo:         CDATA
    ATRIB. Valor:        ert34.doc
Fin del análisis.


Volver al índice