Un ejemplo de lectura SAX con Esquema XML

Ramiro Lago (Enero 2007)

Analizador

Funciona igual que el analizador con DTD. Las diferencias vienen por dos aspectos: primero, a la hora de configurar el 'parser' tenemos que especificar que vamos a usar validación por esquema XML y, en segundo lugar, en el documento XML debemos hacer referencia al Esquema. Empezamos por la configuración del analizador:


    //// Análisis
    SAXParser parser= factoria.newSAXParser();
    Manejador man = new Manejador();
			
    //// El lector valida de acuerdo al esquema
    XMLReader xmlReader = parser.getXMLReader();
    xmlReader.setFeature("http://apache.org/xml/features/validation/schema",true);
		    
    parser.parse( fich, man );		// Parser del fichero 'fich' con el manejador 'man'

El analizador muestra el valor de las las etiquetas 'titulo' y 'autor'. En este ejemplo hacemos una mejora sobre el ejemplo anterior: sólo mostramos el valor (characters) de una etiqueta si es 'libro' o 'autor'


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

/***************************************************************************
* Manejador de eventos SAX
***************************************************************************/
public class Manejador extends DefaultHandler {

    private boolean esTitulo = false;
    private boolean esAutor = false;
 
	....
    public void startElement(String espacioNombres, String nomLocal, String nomCompleto, Attributes atrs) {
		System.out.println("Nombre local:" + nomLocal );
		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) );	
		}
		if (nomLocal.equalsIgnoreCase("titulo"))
			esTitulo = true;
		if (nomLocal.equalsIgnoreCase("autor"))
			esAutor = true;
    }
    public void endElement(String espacio, String nomLocal, String nomCompleto) {
    }
    public void characters(char[] ch, int inicio, int longitud) {
    	if ( esTitulo || esAutor ) {
    		String cad = new String( ch, inicio, longitud);
    		System.out.println("    Caracteres:" + cad );
    		System.out.println("         Inicio:" + inicio + " Longitud:" + longitud );
    		esTitulo = false;
    		esAutor = false;
    	}
    	
    }
    ....
}

En este pequeño ejemplo se ve la ventaja e inconveniente de SAX: es sencillo, pero no se escala de forma fácil, es decir, hay que controlar etiqueta a etiqueta. En nuestro ejemplo sólo tenemos 2, pero imaginemos que tuviesemos 15.

Los documentos

El Esquema (libreria3.xsd) no tiene ninguna particularidad. Señala que 'libros' es una secuencia del tipo 'libro'; a su vez, un libro es una secuencia de 'titulo' y 'autor':



<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="libro">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="titulo" type="xs:token"/>
            <xs:element name="autor" type="xs:token"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:element name="libros" >
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="libro" maxOccurs="unbounded" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

</xs:schema>

El archivo XML hace referencia al Esquema (por sencillez usamos 'file' en vez de 'http'):


<?xml version="1.0" encoding="ISO-8859-1"?>
	<libros xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
		xsi:noNamespaceSchemaLocation="file:C:/DOC/Java_eclipse/docenBasico/src/xmlSAX02/libreria3.xsd"
		xsi:schemaLocation="file:C:/DOC/Java_eclipse/docenBasico/src/xmlSAX02/libreria3.xsd
		 file:C:/DOC/Java_eclipse/docenBasico/src/xmlSAX02/libreria3.xsd">
    <libro>
        <titulo>El fin de una odisea</titulo>
        <autor>Pedro Gomez</autor>
    </libro>
    <libro>
        <titulo>Un lugar en la mente de mi gato</titulo>
		<autor>Anónimo</autor>
    </libro> 
</libros>

Ejemplo de ejecución


El directorio actual es C:\DOC\Java_eclipse\docenBasico
Trato de abrir el archivo C:\DOC\Java_eclipse\docenBasico/src/xmlSAX02/libreria3.xml
Se ha abierto el archivo. Inicio del análisis
Nombre local:libros
    ATRIB. Nombre local: noNamespaceSchemaLocation
    ATRIB. Tipo:         CDATA
    ATRIB. Valor:        file:C:/DOC/Java_eclipse/docenBasico/src/xmlSAX02/libreria3.xsd
    ATRIB. Nombre local: schemaLocation
    ATRIB. Tipo:         CDATA
    ATRIB. Valor:        file:C:/DOC/Java_eclipse/docenBasico/src/xmlSAX02/libreria3.xsd file:C:/DOC/Java_eclipse/docenBasico/src/xmlSAX02/libreria3.xsd
Nombre local:libro
Nombre local:titulo
    Caracteres:El fin de una odisea
         Inicio:1 Longitud:20
Nombre local:autor
    Caracteres:Pedro Gomez
         Inicio:1 Longitud:11
Nombre local:libro
Nombre local:titulo
    Caracteres:Un lugar en la mente de mi gato
         Inicio:1 Longitud:31
Nombre local:autor
    Caracteres:Anónimo
         Inicio:1 Longitud:7
Fin del análisis.


Volver al índice