jueves, 10 de junio de 2010

Android - ¿Cómo parsear un RSS con Xstream?

Hola, este es mi primer blog, así que ténganme paciencia. He visto muchas preguntas en la web sobre cómo parsear un XML proveniente de la web o de algún recurso de la app, y la verdad no he encontrado una solución muy flexible al respecto.

Recomiendan en los foros el uso del SaxParser, y la verdad no me agrada mucho. ¿Que pasa si la estructura del XML cambia? ¿Tengo que cambiar el parseador? No me agrada bastante la idea.

La mejor solución que hallé es la utilización de Xstream, y no he visto en muchos sitios (para no decir no recuerdo haberlo visto en ninguno) una solución Android/Xstream. Por lo que les presento una sencilla implementación de Xstream sobre Android.

Vamos a bajar Xstream desde , sólo nos interesará el xstream-X.X.X.jar que lo incluiremos en nuestra librería del proyecto.

Ahora bien, tomemos un Rss de ejemplo como el que sigue:

http://www.ftovalle.com.ar/rssexample.zip

Renombrar .zip por .xml

Bien, teniendo esta estructura de XML lo que primero debemos hacer es armar un árbol de clases según los atributos del Rss, es decir, como clase principal debemos crear Rss.java, luego Channel.java y seguimos con Item.java. Las mismas clases deben contener las mismas variables de instancia que contenga el XML, vamos a ver con un ejemplo. Abajo paso las clases que mencioné antes, tal cual deberían ser implementadas:

Rss.java

public class Rss {
private Channel channel;

/**
* @return the channel
*/
public Channel getChannel() {
return channel;
}

/**
* @param channel the channel to set
*/
public void setChannel(Channel channel) {
this.channel = channel;
}
}

Channel.java

import java.util.ArrayList;

public class Channel {
private String title;
private String link;
private String description;
private String ttl;
private ArrayList items; //Debemos indicar que Channel contiene una lista de items

/**
* @return the title
*/
public String getTitle() {
return title;
}
/**
* @param title the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @return the link
*/
public String getLink() {
return link;
}
/**
* @param link the link to set
*/
public void setLink(String link) {
this.link = link;
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return the copyright
*/
public String getCopyright() {
return copyright;
}
/**
* @param copyright the copyright to set
*/
public void setCopyright(String copyright) {
this.copyright = copyright;
}
/**
* @return the image
*/
public Image getImage() {
return image;
}
/**
* @param image the image to set
*/
public void setImage(Image image) {
this.image = image;
}
/**
* @return the ttl
*/
public String getTtl() {
return ttl;
}
/**
* @param ttl the ttl to set
*/
public void setTtl(String ttl) {
this.ttl = ttl;
}
/**
* @return the language
*/
public String getLanguage() {
return language;
}
/**
* @param language the language to set
*/
public void setLanguage(String language) {
this.language = language;
}
/**
* @return the items
*/
public ArrayList getItems() {
return items;
}
/**
* @param items the items to set
*/
public void setItems(ArrayList items) {
this.items = items;
}
}
<![CDATA[Clarin.com - Internet]]>

Item.java

public class Item {
private String title;
private String link;
private String description;
private String guid;
private String pubDate;

/**
* @return the title
*/
public String getTitle() {
return title;
}
/**
* @param title the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @return the link
*/
public String getLink() {
return link;
}
/**
* @param link the link to set
*/
public void setLink(String link) {
this.link = link;
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return the guid
*/
public String getGuid() {
return guid;
}
/**
* @param guid the guid to set
*/
public void setGuid(String guid) {
this.guid = guid;
}
/**
* @return the pubDate
*/
public String getPubDate() {
return pubDate;
}
/**
* @param pubDate the pubDate to set
*/
public void setPubDate(String pubDate) {
this.pubDate = pubDate;
}
}

Bien, ya tenemos la estructura de clases que nos va a servir para que Xstream instancie una clase por cada ocurrencia correspondiente que encuentre. Así nos traerá una colección de objetos en memoria (es lo que tanto me gusta de Xstream) .

Último paso, debemos indicarle a Xstream cómo utilizar las clases que escribimos mas arriba. Para ésto creamos un método como el que sigue, explicando cada paso:

public static Rss parseXML(InputStream in) {
// Instanciamos xstream
XStream xstream = new XStream(new DomDriver());
// Le decimos que "rss" lo tome como una clase Rss
xstream.alias("rss", Rss.class);
// Le decimos que va a haber una lista de objetos en la clase Channel, la cual tiene una
// variable de instancia llamada "items", la cual quiero que cada uno de estos "items" sean
// del timpo Item.class
xstream.addImplicitCollection(Channel.class, "items", "item", Item.class);

Rss rss = (Rss) xstream.fromXML(in);

return rss;
}

Y listo. La salida de este método nos dará un objeto del tipo Rss, con un Channel dentro de el, y éste teniendo una lista de items (en este caso 2).

Espero les sirva.

Saludos,
ftovalle











<![CDATA[Clarin.com]]>





<![CDATA[India: bloquean Facebook por contenidos contra el Islam]]>











<![CDATA[El científico Mark Gasson cuenta a la BBC los objetivos de su investigación (en inglés).]]>














No hay comentarios: