En los artículos anteriores dedicados al tratamiento de XML en aplicaciones Android (parte 1, parte 2, parte 3) dentro de nuestro tutorial de programación Android hemos comentado ya los modelos SAX y DOM, los dos métodos más comunes de lectura de XML soportados en la plataforma.
En este cuarto artículo nos vamos a centrar en el último método menos conocido, aunque igual de válido según el contexto de la aplicación, llamado XmlPull. Este método es una versión similar al modelo StAX (Streaming API for XML), que en esencia es muy parecido al modelo SAX ya comentado. Y digo muy parecido porque también se basa en definir las acciones a realizar para cada uno de los eventos generados durante la lectura secuencial del documento XML. ¿Cuál es la diferencia entonces?
La diferencia radica principalmente en que, mientras que en SAX no teníamos control sobre la lectura del XML una vez iniciada (el parser lee automáticamente el XML de principio a fin generando todos los eventos necesarios), en el modelo XmlPull vamos a poder guiar o intervenir en la lectura del documento, siendo nosotros los que vayamos pidiendo de forma explícita la lectura del siguiente elemento del XML y respondiendo al resultado ejecutando las acciones oportunas.
Veamos cómo podemos hacer esto:
public class RssParserPull { private URL rssUrl; public RssParserPull(String url) { try { this.rssUrl = new URL(url); } catch (MalformedURLException e) { throw new RuntimeException(e); } } public List<Noticia> parse() { List<Noticia> noticias = null; XmlPullParser parser = Xml.newPullParser(); try { parser.setInput(this.getInputStream(), null); int evento = parser.getEventType(); Noticia noticiaActual = null; while (evento != XmlPullParser.END_DOCUMENT) { String etiqueta = null; switch (evento) { case XmlPullParser.START_DOCUMENT: noticias = new ArrayList<Noticia>(); break; case XmlPullParser.START_TAG: etiqueta = parser.getName(); if (etiqueta.equals("item")) { noticiaActual = new Noticia(); } else if (noticiaActual != null) { if (etiqueta.equals("link")) { noticiaActual.setLink(parser.nextText()); } else if (etiqueta.equals("description")) { noticiaActual.setDescripcion(parser.nextText()); } else if (etiqueta.equals("pubDate")) { noticiaActual.setFecha(parser.nextText()); } else if (etiqueta.equals("title")) { noticiaActual.setTitulo(parser.nextText()); } else if (etiqueta.equals("guid")) { noticiaActual.setGuid(parser.nextText()); } } break; case XmlPullParser.END_TAG: etiqueta = parser.getName(); if (etiqueta.equals("item") && noticiaActual != null) { noticias.add(noticiaActual); } break; } evento = parser.next(); } } catch (Exception ex) { throw new RuntimeException(ex); } return noticias; } private InputStream getInputStream() { try { return rssUrl.openConnection().getInputStream(); } catch (IOException e) { throw new RuntimeException(e); } } }
Centrándonos una vez más en el método parse(), vemos que tras crear el nuevo parser XmlPull y establecer el fichero de entrada en forma de stream [mediante XmlPull.newPullParser() y parser.setInput(…)] nos metemos en un buble en el que iremos solicitando al parser en cada paso el siguiente evento encontrado en la lectura del XML, utilizando para ello el método parser.next(). Para cada evento devuelto como resultado consultaremos su tipo mediante el método parser.getEventType() y responderemos con las acciones oportunas según dicho tipo (START_DOCUMENT, END_DOCUMENT, START_TAG, END_TAG). Una vez identificado el tipo concreto de evento, podremos consultar el nombre de la etiqueta del elemento XML mediante parser.getName() y su texto correspondiente mediante parser.nextText(). En cuanto a la obtención del texto, con este modelo tenemos la ventaja de no tener que preocuparnos por «recolectar» todos los fragmentos de texto contenidos en el elemento XML, ya que nextText() devolverá todo el texto que encuentre hasta el próximo evento de fin de etiqueta (ENT_TAG).
Y sobre este modelo de tratamiento no queda mucho más que decir, ya que las acciones ejecutadas en cada caso son análogas a las que ya vimos en los artículos anteriores.
Puedes consultar y/o descargar el código completo de los ejemplos desarrollados en este artículo accediendo a la página del curso en GitHub.
Espero haber sido capaz de mostrar con claridad en estos cuatro artículos todas las posibilidades existentes a la hora de leer y procesar documentos XML en aplicaciones Android.
Curso de Programación Android en PDF
¿Te ha sido de utilidad el Curso de Programación Android? ¿Quieres colaborar de forma económica con el proyecto? Puedes contribuir con cualquier cantidad, unos céntimos, unos euros, cualquier aportación será bienvenida. Además, si tu aportación es superior a una pequeña cantidad simbólica recibirás como agradecimiento un documento con la última versión del curso disponible en formato PDF. Sea como sea, muchas gracias por colaborar!
Más información:
13 comentarios
[…] This post was mentioned on Twitter by Babelias, Salva. Salva said: Último artículo sobre tratamiento de XML en #Android, esta vez para describir el modelo XmlPull [http://www.sgoliver.net/blog/?p=1604] […]
Gracias por el curso,voy a ponerme a ello.
[…] Tratamiento de XML en Android (IV): XmlPull […]
Hola! Gracias por el tuto!
La duda que tengo es que si mi servicio web me envia el xml como una srting, como lo trato?
Porqué tu siempre pones cogiendo de una dirección.
A ver si me ayudas! Gracias! ;)
Me pasa lo mismo que a Jaume.
[…] ya algún tiempo dedicamos varios artículos (I, II, III, IV) al tratamiento de ficheros XML en Android y vimos varias alternativas a la hora de leer (parsear) […]
Si tienes un string, tienes que modificar
parser.setInput(this.getInputStream(), null);
por:
parser.setInput(new StringReader(String_en_xml));
Hola, perfecto tuto! Pero podrias poner un ejemplo de como mostra los datos en pantalla (con cualquier de los 4 métodos)
Gracias
Amigos, la parte del input ya no es compatible con 4.1
parser.setInput(getInputStream(),null);
parser.setInput(new InputStreamReader(getInputStream()));
lo ha revisado?
Hola Nelson, no entiendo exactamente cuál es tu problema ¿te aparece algún error concreto?
El parser me lanza el siguiente error:
09-30 11:04:18.569: W/System.err(3987): org.apache.harmony.xml.ExpatParser$ParseException: At line 8, column 6: junk after document element
en el caso de que el XML tenga mas de un elemento. Por ejemplo:
Juan
18
Pedro
21
Cuando solo tiene un elemento me parsea sin problema. Ejemplo:
Pedro
21
[…] Tratamiento de XML en Android (IV): XmlPull [v3] […]
Buena noches te felicito excelente post. Tengo varios archivos xml que debo cargar en la base datos interna del móvil. Entre los archivo tengo data que puede variar en un promedio de 3000 a 70000 registros, ¿Cuál de lo métodos que has trabajado consideras el más veloz?.
Antemano. Muchas Gracias por tiempo