Este capitulo merece leerselo poco a poco. Java nos ofrece dos modelos de parseador XML: Uno es Serial Access Xml y el otro es Document Object Model. El mejor y más sencillo de usar es el DOM. Por contrapartida es el mas lento y pesado. Por lo que yo, amante de las cafeteras y máquinas viejas me decanto en primera instancia por el SAX dado que es más ligero rápido para mi viejo Intel PentiumII.
SAX tien 2 inconvenientes.
Una vez explicados los inconvenientes y ventajas (es mas ligero) de SAX voy a contarte como funciona un poco por encina. Si quieres una explicación mas detallada vete a la página de Sun
El caso es que SAX es una modelo de manipulación XML. Lo mas inportante en todo esto es el DocumentHandler, el manipulador del documento que es donde le vas a indicar lo que tiene que hacer el parseador.
La cosa va tal que así: Tu declaras una factoría parseadora. Y de esa factoria parseadora le dices que cree un parseador. Y a se parseador le pasas tu DocumentHandler que es donde le dices lo que tiene que hacer en cada momento.
El DocumentHandler es una interfaz que responde a eventos. Por lo que se llamarán los métodos especificados cuando suceda algo en concreto. Los métodos principales son:
Uno de los diseños más sencillos es el de implementar una clase interna que sea tu DocumentHandler. En ese caso simplemente extiendes la clase de DefaultHandler y implementas los métodos deseados. Como puedes ver en este sencilliiiiisimo ejemplo:
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class LectorSAX {
public void lee(String url){
try{
SAXParserFactory spf=SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
sp.parse(url, new LibraryXMLReader() );
}catch(ParserConfigurationException e){
System.err.println("error de parseo");
}catch(SAXException e2){
System.err.println("error de sax : " + e2.getStackTrace());
} catch (IOException e3) {
// TODO Auto-generated catch block
System.err.println("error de io : " + e3.getMessage() );
}
}
public static void main(String[] args){
LectorSAX lector = new LectorSAX();
lector. lee("http://badopi.net/atom.xml");
}
//---------------------------------------------------------------------------------
private class LibraryXMLReader extends DefaultHandler {
String contenido=""; // cadena para almacenar el contenido de un tag
public void startDocument() throws SAXException{
System.out.println("Estoy al principio del documento");
}
public void endDocument()throws SAXException{
System.out.println("Estoy al final del documento");
}
/* Esta funcion el llamada cuando se produce el evento
* de(non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
public void startElement(String uri, String localName, String qName, Attributes attributes) {
System.out.println("he encontrado una nueva etiqueta :" + qName);
}
/* Esta funcion es llamada cuando ve el contenido de un tag
* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
*/
public void characters(char buf[], int offset, int len)
throws SAXException
{
contenido = new String(buf, offset, len);
}
/* y esta al llegar al final
* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
public void endElement(String uri, String localName, String qName) {
System.out.println("he leido la etiqueta : " + qName + " y su contenido es : " + contenido);
}
}
}
Una buena idea para parsear un XML a traves de SAX y poder manipularlo luego tranquilamente es crearte un objeto que te almacene los datos. de ese modo tu puedes manipular el contenido del XML después a tu gusto. Espero que este ejemplo te sirva de ayuda:
Clase almacenadora de datos ( las malas lenguas dicen que a esto se le llama BEAN)
public class OrigenXML {
private String titulo, descripcion, enlace, fecha;
public void setTitulo(String titulo) {
this.titulo = titulo;
}
public String getTitulo() {
return titulo;
}
public void setFecha(String titulo) {
this.fecha = titulo;
}
public String getFecha() {
return fecha;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
public String getDescripcion() {
return descripcion;
}
public void setEnlace(String enlace) {
this.enlace = enlace;
}
public String getEnlace() {
return enlace;
}
}
Una vez que tienes esta clase puedes modificar el ejemplo anterior para que te meta el contenido del XML en ella:
import java.io.IOException;
import java.util.ArrayList;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class LectorSAX {
ArrayList nodos;
public ArrayList getNodos(){
return this.nodos;
}
public LectorSAX(String url){
nodos = new ArrayList();
try{
SAXParserFactory spf=SAXParserFactory.newInstance(); // creo la factoría sax
SAXParser sp = spf.newSAXParser(); // creo el parseador
sp.parse(url, new LibraryXMLReader() ); // al parseador le digo que parsee la url que quiero con el
}catch(ParserConfigurationException e){ // manipulador de documento (documentHandler) que quiero
System.err.println("error de parseo"); // (la url es una url o una path de tu ordenador se lo
}catch(SAXException e2){ // traga igual )
System.err.println("error de sax : " + e2.getStackTrace());
} catch (IOException e3) {
// TODO Auto-generated catch block
System.err.println("error de io : " + e3.getMessage() );
}
}
private class LibraryXMLReader extends DefaultHandler {
String contenido="";
private OrigenXML nodoActual= new OrigenXML();
/*
* Esta funcion el llamada cuando se produce el evento de ver una nueva etiqueta
*/
public void startElement(String uri, String localName, String qName, Attributes attributes) {
if ("item".equals(qName)) {
nodoActual = new OrigenXML();
}
}
/*
* Esta funcion es llamada cuando ve el contenido de una etiqueta
*/
public void characters(char buf[], int offset, int len)
throws SAXException
{
contenido = new String(buf, offset, len);
}
/*
* y esta al llegar al final
*/
public void endElement(String uri, String localName, String qName) {
if("title".equals(qName)){
nodoActual.setTitulo(contenido);
}
if("link".equals(qName)) {
nodoActual.setEnlace(contenido);
}
if("description".equals(qName)) {
nodoActual.setDescripcion(contenido);
}
if("pubDate".equals(qName)) {
nodoActual.setFecha(contenido);
}
if("item".equals(qName)) {
nodos.add(nodoActual);
}
}
}
}
De este modo ya tengo el contenido de mi lector de XML en el ArrayList de nodos que devolveré cuando me lo pidan. Y ese ArrayList son los objetos OrigenXML que contienen la información que a mi me interesa.