9 Acceso a ficheros XML con SAX¶
Introducción¶
SAX (API Simple para XML) es un conjunto de clases e interfaces que ofrecen una herramienta muy útil para el procesamiento de documentos XML. Permite analizar los documentos de forma secuencial, lo que implica poco consumo de memoria aunque los documentos sean de gran tamaño. Pero por lo contrario, impide tener una visión global del documento que se va a analizar.
SAX es más complejo de programar que DOM, ya que es una API totalmente escrita en Java e incluida dentro del JRE que nos permite crear nuestro propio parser de XML.
Lectura de un documento XML¶
La lectura de un documento XML produce eventos que ocasiona la llamada a métodos, los eventos son encontrar la etiqueta de inicio y fin del documento (startDocument() y endDocument()), la etiqueta de inicio y fin de un elemento (startElement() y endElement()), los caracteres entre etiquetas (characters()), etc.
Documentos XML | Métodos asociados a eventos del documento |
---|---|
<?xml version="1.o"?><listadealumnos> <alumno> <nombre> Juan </nombre> <edad> 19 </edad> </alumno> <alumno><br/> <nombre> María </nombre> <edad> 20 </edad> </alumno> </listadealumnos> | starDocument() starElement() startElement() startElement() characters() endElement() startElement() characters() endElement() endElement() starElement() startElement() startElement() characters() endElement() startElement() characters() endElement() endElement() endDocument() |
Para leer un documento se crea un objeto procesador de XML, un XMLReader, que puede producir un excepción SAXException que es necesario capturar.
A continuación hay que indicar al XMLReader que objetos poseen los métodos que tratarán los eventos. Estos objetos serán normalmente implementaciones de las siguientes interfaces:
- ContentHandler: Recibe las notificaciones de los eventos que ocurren en el documento.
- DTDHandler: Recoge eventos relacionados con la DTD.
- ErrorHandle: Define los métodos de tratamientos de errores.
- EntityResolver: Sus métodos se llaman cada vez que se encuentra una referencia a una entidad.
- DefaultHandler: Clase que provee una implementación por defecto para todos sus métodos, el programador definirá los métodos que sean utilizados por el programa. Esta clase es de la que se extenderá para poder crear una clase parser de XML:
- startDocument(): se produce al comenzar el procesado del documento XML.
- endDocument(): se produce al finalizar el procesado del documento XML.
- startElement(): se produce al finalizar el procesado del documento XML.
- endElement(): se produce al finalizar el procesado de una etiqueta XML.
- characters(): se produce al encontrar una cadena de texto.
Para indicar al procesador XML los objetos que realizarán el tratamiento se utilizan alguno de los siguientes métodos incluidos dentro de los objetos XMLReader: setContentHandler(), setDTDHandler(), setEntityResolver() y setErrorHandler(); cada uno trata un tipo de evento asociado a una interfaz determinada. Después se lee mediante el objeto InputSource.
public class GestorDeContenidos extends DefaultHandler {
public GestorDeContenidos() { super(); }
@Override
public void startDocument() throws SAXException {
System.out.println("Comienzo del Documento XML");
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.printf("\tPrincipio Elemento: %s\n", localName);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
String car = new String(ch, start, length);
car = car.replaceAll("[\t\n]", "");
System.out.printf("\tCaracteres: %s\n", car);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.printf("\tFin Elemento: %s\n", localName);
}
@Override
public void endDocument() throws SAXException {
System.out.println("Final del Documento");
}
}
public class ReadSax {
public void show() throws SAXException, IOException, ParserConfigurationException {
XMLReader procesadorXML = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); //XMLReaderFactory.createXMLReader();
HandlerContent handler = new HandlerContent();
procesadorXML.setContentHandler(handler);
InputSource fileXML = new InputSource("file.xml");
procesadorXML.parse(fileXML);
}
public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException {
new ReadSax().show();
}
}
Atributos XML¶
Un fichero XML puede contener atributos, por lo que podemos recorrerlos al recorrer el elemento:
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
int i;
System.out.println("\nProcesando etiqueta...");
System.out.println("\tNamespace uri: "+uri);
System.out.println("\tNombre: "+localName);
System.out.println("\tNombre con prefijo: "+name);
//Recorremos los atributos
System.out.println("\tProcesando "+attributes.getLength()+" atributos...");
for(i=0;i<attributes.getLength();i++){
System.out.println("\t\tNombre: "+attributes.getQName(i));
System.out.println("\t\tValor: "+attributes.getValue(i));
}
// También podemos obtener los atributos por nombre
String valorId = attributes.getValue("id");
if(valorId!=null){
System.out.println("\tId: "+valorId);
}
}
Estilos con XSL¶
XSL (Extensible Stylesheet Language) es una recomendación para expresar hojas de estilo en lenguaje XML. Una hoja de estilo XSL describe el proceso de presentación a través de un pequeño conjunto de elementos XML.
Una hoja de estilo XSL describe el proceso de presentación a través de un pequeño conjunto de elementos XML. Esta hoja, puede contener elementos de reglas que representan a las reglas de construcción y elementos de reglas de estilo que representan a las reglas de mezcla de estilos.
<?xml version="1.0" encoding='ISO-8859-1'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match='/'>
<html><xsl:apply-templates /></html>
</xsl:template>
<xsl:template match='listadealumnos'>
<head><title>LISTADO DE ALUMNOS</title></head>
<body>
<h1>LISTA DE ALUMNOS</h1>
<table border='1'>
<tr><th>Nombre</th><th>Edad</th></tr>
<xsl:apply-templates select='alumno' />
</table>
</body>
</xsl:template>
<xsl:template match='alumno'>
<tr><xsl:apply-templates /></tr>
</xsl:template>
<xsl:template match='nombre|edad'>
<td><xsl:apply-templates /></td>
</xsl:template>
</xsl:stylesheet>
Para realizar la transformación se necesita obtener un objeto Transformer que se obtiene creando una instancia de TransformerFactory y aplicando el método newTransformer(Source source) a la fuente XSL que se va a utilizar para aplicar la transformación, o lo que es lo mismo, para aplicar la hoja de estilos XSL al fichero XML.
public class XLS {
public void show() throws IOException {
String hojaEstilo = "alum_template.xsl";
String datosAlumnos = "alum.xml";
File pagHTML = new File("page.html");
FileOutputStream os = new FileOutputStream(pagHTML);
Source estilos = new StreamSource(hojaEstilo); // fuenteXSL
Source datos = new StreamSource(datosAlumnos); // fuenteXML
Result result = new StreamResult(os);
try{
Transformer transformer = TransformerFactory.newInstance().newTransformer(estilos);
transformer.transform(datos, result);
} catch (Exception e){
System.err.println("Error: "+ e);
}
os.close();
}
public static void main(String[] args) throws IOException {
new XLS().show();
}
}