Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Web Services
(Tratamiento de XML)
Tratamiento XML
Para el manejo exclusivo de XML, tendremos 4 maneras de tratarlos, los cuales los mencionamos a continuacin:
1. 2. 3. 4.
Tratamiento de XML con SAX. Tratamiento de XML con SAX Simplificado. Tratamiento de XML con DOM. Tratamiento de XML con XmlPull.
Tratamiento XML
Utilizaremos el archivo llamado primerXml.xml, de nuestra carpeta XMLS Como podemos observar el xml se compone de un elemento principal <channel> y posteriormente una lista de elementos <item> para cada noticia con sus datos asociados. Para poder trabajar, procederemos a crear nuestro modelo; llamado Noticia, al cual le colocaremos los siguiente atributos, y generaremos sus mtodos de acceso.
private String titulo; private String link; private String descripcion; private String guid; private String fecha;
(*) Definiremos a todos los mtodos como String para no complicarnos en el desarrollo del laboratorio.
Ahora, que ya sabemos con que estructura y que clase auxiliar vamos a trabajar procederemos a detallar cada modelo, cualquiera de los mencionados anteriormente pueden tratar XML de manera online como local, pero dependiendo del contexto veremos cual resulta mas eficiente para ciertos escenarios. Como estamos viendo Servicios Web, nos centraremos en xml Online.
Tratamiento XML
Puntos a seguir, para el tratamiento XML:
1. 2. 3. 4.
Tratamiento de XML con SAX. Tratamiento de XML con SAX Simplificado. Tratamiento de XML con DOM. Tratamiento de XML con XmlPull.
startDocument(): comienza el documento XML. endDocument(): termina el documento XML. startElement(): comienza una etiqueta XML. endElement(): termina una etiqueta XML. characters(): fragmento de texto.
Lista Completa:
http://developer.android.com/reference/org/xml/sax/helpers/DefaultHandler.html
Vamos a generar un Listado de Noticias, y con el mtodo getNoticias() [Lo realizaremos con el mtodo de acceso para get()] obtendremos las noticias tras el termino de lectura del documento. Ahora comencemos con los eventos SAX necesarios.
Ahora procederemos con el evento startElement() se lanza cada vez que se encuentra una nueva etiqueta de apertura. En nuestro caso, la nica etiqueta que nos interesar ser <item>, momento en el que inicializaremos un nuevo objeto auxiliar de tipo Noticia donde almacenaremos posteriormente los datos de la noticia actual.
if (localName.equals("item")) { noticiaActual = new Noticia(); }
}
Por ltimo, en el evento endElement(), lo que haremos ser almacenar en el objeto noticiaActual (que conoceremos por el parmetro localName devuelto por el evento) el texto que hemos ido acumulando en la variable sbTexto y limpiaremos dicha variable para comenzar a acumular el siguiente dato. El nico caso especial ser cuando detectemos el cierre de la etiqueta <item>, que significar que hemos terminado de leer todos los datos de la noticia y por tanto aprovecharemos para aadir la noticia actual a la lista de noticias que estamos construyendo.
Constructor
public NoticiaParserSax(String url){ try{ this.noticiaUrl = new URL(url); }catch (MalformedURLException e){ throw new RuntimeException(e); } }
El constructor de la clase se limitar a aceptar como parmetro la URL del documento XML a parsear a controlar la validez de dicha URL, generando una excepcin en caso contrario.
public List<Noticia> parse(){ SAXParserFactory factory = SAXParserFactory.newInstance(); try{ SAXParser parser = factory.newSAXParser(); NoticiasHandler handler = new NoticiasHandler(); parser.parse(this.getInputStream(), handler); return handler.getNoticias(); }catch (Exception e){ throw new RuntimeException(e); } }
Ser el encargado de crear un nuevo parser SAX mediante su fbrica correspondiente y de iniciar el proceso pasando al parser una instancia del handler que hemos creado anteriormente y una referencia al documento a parsear en forma de stream.
private InputStream getInputStream(){ try{ return noticiaUrl.openConnection().getInputStream(); }catch (IOException e){ throw new RuntimeException(e); } }
Se encarga de abrir la conexin con la URL especificada mediante openConnection() y obtener el stream de entrada
Ahora solamente en nuestro Activity nos falta enviarle el url al momento de crear un nuevo ParserSax; y no nos olvidemos del permiso hacia internet. NoticiaParserSax saxparser = new NoticiaParserSax("http://www.e-linguasac.com/primerXml.xml"); List<Noticia> noticias = saxparser.parse();
Tratamiento XML
Puntos a seguir, para el tratamiento XML:
1. 2. 3. 4.
Tratamiento de XML con SAX. Tratamiento de XML con SAX Simplificado. Tratamiento de XML con DOM. Tratamiento de XML con XmlPull.
try{
this. noticiaUrl = new URL(url); } catch (MalformedURLException e){ throw new RuntimeException(e); }
public List<Noticia> parse(){ final List<Noticia> noticias = new ArrayList<Noticia>(); RootElement root = new RootElement("rss"); Element channel = root.getChild("channel"); Element item = channel.getChild("item"); //Aqu comenzaremos a leer el documento en si. }
item.setStartElementListener(new StartElementListener(){ public void start(Attributes attrs) { noticiaActual = new Noticia(); } });
Para finalizar la lectura del documento, procedemos a realizar setEndElementListener(), y luego procedemos a agregar a la lista noticias, los objetos noticiaActual.
item.getChild("title").setEndTextElementListener(new EndTextElementListener(){ public void end(String body) { noticiaActual.setTitulo(body); } }); item.getChild("link").setEndTextElementListener(new EndTextElementListener(){ public void end(String body) { noticiaActual.setLink(body); } });
try{
private InputStream getInputStream(){ try{ return noticiaUrl.openConnection().getInputStream(); } catch (IOException e){ throw new RuntimeException(e); } }
Como ya sabemos este mtodo es el que nos permitir crear el acceso o la entrada al Stream.
if (android.os.Build.VERSION.SDK_INT > 9) {
Tratamiento XML
Puntos a seguir, para el tratamiento XML:
1. 2. 3. 4.
Tratamiento de XML con SAX. Tratamiento de XML con SAX Simplificado. Tratamiento de XML con DOM. Tratamiento de XML con XmlPull.
<noticias> <noticia> <titulo>T1</titulo> <link>L1</link> </noticia> <noticia> <titulo>T2</titulo> <link>L2</link> </noticia> <noticias>
Como vemos, este rbol conserva la misma informacin contenida en el fichero XML pero en forma de nodos y transiciones entre nodos, de forma que se puede navegar fcilmente por la estructura.
Ahora comenzaremos a realizar el parser mediante DOM para poder realizar la comparativa con SAX. Para esto crearemos la clase NoticiaParseDom. Como hasta el momento hemos visto siempre manejamos una ruta, en este caso tambin tendremos que definirla.
Parmetro URL: Constructor private URL noticiaUrl;
public NoticiaParserDom(String url){ try{ this.noticiaUrl = new URL(url); }catch (MalformedURLException e){ throw new RuntimeException(e); } }
public List<Noticia> parse(){ //Instanciamos la fbrica para DOM DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); List<Noticia> noticias = new ArrayList<Noticia>(); //Aqu comenzaremos a leer el documento en si. }
Simplemente instanciamos para crear nuestro factory con el cual utilizaremos para crear nuestro parser.
try{ //Creamos un nuevo parser DOM DocumentBuilder builder = factory.newDocumentBuilder(); //Realizamos la lectura completa del XML Document dom = builder.parse(this.getInputStream()); //Nos posicionamos en el nodo principal del rbol (<rss>) Element root = dom.getDocumentElement(); //Localizamos todos los elementos <item> NodeList items = root.getElementsByTagName("item"); //AQU CONTINUAREMOS REALIZANDO LA LECTURA }catch (Exception ex){ throw new RuntimeException(ex); } return noticias;
//Recorremos la lista de noticias for (int i=0; i<items.getLength(); i++){ Noticia noticia = new Noticia(); //Obtenemos la noticia actual Node item = items.item(i); //Obtenemos la lista de datos de la noticia actual NodeList datosNoticia = item.getChildNodes();
Sabemos que items, es el que va almacenar las noticias del xml, entonces procedemos a recorrerlo. Hay que tener presente que NodeList, reconoce todos los elementos que le coloquemos y los almacena en memoria para su posterior utilizacin.
for (int j=0; j<datosNoticia.getLength(); j++){ Node dato = datosNoticia.item(j); String etiqueta = dato.getNodeName(); if (etiqueta.equals("title")){ String texto = obtenerTexto(dato); noticia.setTitulo(texto); }else if (etiqueta.equals("link")){ noticia.setLink(dato.getFirstChild().getNodeValue()); }else if (etiqueta.equals("description")){ String texto = obtenerTexto(dato); noticia.setDescripcion(texto); }else if (etiqueta.equals("guid")){ noticia.setGuid(dato.getFirstChild().getNodeValue()); }else if (etiqueta.equals("pubDate")){ noticia.setFecha(dato.getFirstChild().getNodeValue()); } } noticias.add(noticia);
if (etiqueta.equals("title")){ String texto = obtenerTexto(dato); noticia.setTitulo(texto); }else if (etiqueta.equals("description")){ String texto = obtenerTexto(dato); noticia.setDescripcion(texto); }
Como vimos en el ejemplo grfico de rbol DOM, el texto de un nodo determinado se almacena como nodo hijo. Este nodo de texto suele ser nico, por lo que la forma habitual de obtener el texto de un nodo es obtener su primer nodo hijo y obtener su valor:
private String obtenerTexto(Node dato){ StringBuilder texto = new StringBuilder(); NodeList fragmentos = dato.getChildNodes(); for (int k=0;k<fragmentos.getLength();k++){ texto.append(fragmentos.item(k).getNodeValue()); } return texto.toString(); }
En nuestro mtodo de obtenerTexto vamos a enviar el Nodo del cual vamos a comenzar a concatenar y realizamos el mismo procedimiento como si estuviramos leyendo cualquier NodeList.
Finalmente instanciaremos a nuestra clase NoticiaParserDom desde el Activity Main, y ya tenemos el tratamiento XML con DOM.
Tratamiento XML
Puntos a seguir, para el tratamiento XML:
1. 2. 3. 4.
Tratamiento de XML con SAX. Tratamiento de XML con SAX Simplificado. Tratamiento de XML con DOM. Tratamiento de XML con XmlPull.
Crearemos nuestra clase NoticiaParserPull, en la cual como ya sabemos crearemos nuestro mtodo de validacin de URL.
En nuestro mtodo parser, definiremos estos 2 atributos, y los inicializarlos List<Noticia> noticias = null; XmlPullParser parser = Xml.newPullParser();
Creamos nuestro try catch que venimos utilizando y retornamos la lista de noticias.
Nos centraremos principalmente en el evento, el cual nos indicar si estamos iniciando el documento, tambin el inicio de los tag y dems. Comenzaremos con crear un while, con dicha estructura vamos a recorrer el documento. while (evento != XmlPullParser.END_DOCUMENT){ String etiqueta = null; //comenzaremos a recorrer las etiquetas
evento = parser.next(); }
Caso contrario es cuando ya no item y son las dems etiquetas que pueden ser su contenido, propiamente dicho: else if (noticiaActual != null){ //analizar las demas etiquetas //title, description y dems }
Comenzaremos a leer las etiquetas y comparamos para setear el valor en el objeto Noticia.
case XmlPullParser.END_TAG: etiqueta = parser.getName(); if (etiqueta.equals("item") && noticiaActual != null){ noticias.add(noticiaActual); } break;
El ltimo case de nuestro switch nos indicar que ya hemos terminado el tag y agregamos el objeto tipo Noticias a nuestro listado llamado noticias. (*) No nos olvidemos de agregarlo en nuestro Activity.