Building Android and iPhone applications from scratch
In: Android| Tutoriales
7 Ago 2009Una de las muchas funciones interesantes que nos ofrece Android es poder leer datos de un fichero XML. A simple vista puede parecer algo bastante trivial, pero sin éstos métodos hay una gran cantidad de informacion en Internet que no podremos obtener. [tweetmeme]
Gracias a métidos como SAXParser (SAX es la abreviatura de Simple API para XML) podremos leer contenido de un fichero XML para después tratarlo a nuestro antojo.
¿Qué es esto?
En éste tutorial vamos a leer contenido de un fichero XML y lo mostraremos por pantalla.
¿Qué voy a aprender?
¿Cómo quedará?

Pasos a seguir:
Como veis a nivel visual se trata de una aplicación muy sencilla, la información que leamos del XML la mostraremos por pantalla mediante un TextView. No es necesario modificar el fichero main.xml, mostraremos el texto al vuelo.
Para poder tratar un fichero XML primero debemos conocer su estructura, en nuestro caso se trata de un simple fichero que incluye los datos de una ubicación:
ejemplo.xml:
<ejemplo> <titulo>Mobile Development</titulo> <valoracion>4</valoracion> <distancia>6.7762437412613</distancia> <coordenadas>40.4784,-3.71233</coordenadas> <telefono>91 386 2393</telefono> −<cireccion> <calle>Paseo Maritimo Rafael de Casanovas</calle> <numero numerodecalle="7"/> <ciudad>Tarragona</ciudad> <categoria lang="Programacion"</title> </categoria></cireccion></ejemplo>
Para poder leer los datos del fichero XML necesitamos un XMLReader y un ContentHandler. El XMLReader es quien se encarga de leer los datos (un punto para el ingeniero) y el ContentHandler es quien le dice al XMLReader como tratar esos datos.
Lo que vamos a hacer ahora es abrir la dirección URL donde está alojado el fichero, crearemos el SAXParser, le añadiremos un ContentHandler, pasaremos los datos desde la URL y los mostraremos por pantalla.
ParsingXML.java:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Create a new TextView to display the parsingresult later. */
TextView tv = new TextView(this);
try {
/* URL desde donde leeremos los datos. */
String URL_Test = "http://www.tech-xperience.com/mobiledev/places.xml";
URL url = new URL(URL_Test);
/* Creamos un SAXParser. */
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
/* Cogemos el XMLReader del SAXParser que hemos creado. */
XMLReader xr = sp.getXMLReader();
/* Creamos un nuevo ContentHandler y lo aplicamos al XML-Reader*/
XMLHandler myXMLHandler = new XMLHandler();
xr.setContentHandler(myXMLHandler);
/* Tratamos los datos del URL. */
xr.parse(new InputSource(url.openStream()));
/* Acaba el tratamiento. */
/* Ponemos los datos por pantalla con el XMLHandler. */
ParsedXMLDataSet parsedExampleDataSet = myXMLHandler.getParsedData();
/* Set the result to be displayed in our GUI. */
tv.setText(parsedExampleDataSet.toString());
} catch (Exception e) {
/* Mostramos el Error. */
tv.setText("Error: " + e.getMessage());
Log.e(MY_DEBUG_TAG, "XMLQueryError", e);
}
/* Display the TextView. */
this.setContentView(tv);
}
La siguiente clase que definiremos es el ContentHandler, en nuestro caso un SAX-Handler que se ocupará de recorrer el archivo XML.
Cuando se encuentre con tag de apertura como,
<ejemplo>
se ejecutará la funcion del Handler:
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {}
Lo mismo ocurre al encontrarse con un tag de cierre como,
</ejemplo>
se ejecutará la funcion del Handler:
@Override
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {}
Para leer los datos dentro de un tag como el anterior debemos usar la función:
@Override public void characters(char ch[], int start, int length)}
En caso de que el contenido que queremos leer se encuentre de ésta manera
<numero numerodecalle="7"/>
Deberemos acceder a él dentro de la función startElement
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {}
Visto así no parece muy claro, veamos el código completo para entenderlo mejor.
XMLHandler.java:
package com.mobiledev;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XMLHandler extends DefaultHandler{
// ===========================================================
// Campos
// ===========================================================
@SuppressWarnings("unused")
private boolean in_ejemplo = false;
private boolean in_titulo = false;
private boolean in_valoracion = false;
private boolean in_distancia = false;
private boolean in_coordenadas = false;
private boolean in_telefono = false;
@SuppressWarnings("unused")
private boolean in_direccion = false;
@SuppressWarnings("unused")
private boolean in_categoria = false;
private boolean in_calle = false;
@SuppressWarnings("unused")
private boolean in_numero = false;
private boolean in_ciudad = false;
private ParsedXMLDataSet myParsedXMLDataSet = new ParsedXMLDataSet();
// ===========================================================
// Getter & Setter
// ===========================================================
public ParsedXMLDataSet getParsedData() {
return this.myParsedXMLDataSet;
}
// ===========================================================
// Metodos
// ===========================================================
@Override
public void startDocument() throws SAXException {
this.myParsedXMLDataSet = new ParsedXMLDataSet();
}
@Override
public void endDocument() throws SAXException {
// No hacemos nada
}
/** Se ejecuta cuando encuentra tags como:
* <tag>
* Puede leer atributos cuando se encuentra con:
* </tag><tag attribute="attributeValue">*/
@Override
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
if (localName.equals("ejemplo")) {
this.in_ejemplo = true;
}else if (localName.equals("titulo")) {
this.in_titulo = true;
}else if (localName.equals("valoracion")) {
this.in_valoracion = true;
}else if (localName.equals("distancia")) {
this.in_distancia = true;
}else if (localName.equals("coordenadas")) {
this.in_coordenadas = true;
}else if (localName.equals("telefono")) {
this.in_telefono = true;
}else if (localName.equals("direccion")) {
this.in_direccion = true;
}else if (localName.equals("calle")) {
this.in_calle = true;
}else if (localName.equals("numero")) {
// Extraemos el atributo
String attrValue = atts.getValue("numerodecalle");
int i = Integer.parseInt(attrValue);
myParsedXMLDataSet.setNumCalle(i);
}else if (localName.equals("ciudad")) {
this.in_ciudad = true;
}else if (localName.equals("categoria")) {
// Extraemos el atributo
String attrValue = atts.getValue("lang");
myParsedXMLDataSet.setCategoria(attrValue);
}
}
/** Se ejecuta en tags de cierre:
* </tag> */
@Override
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if (localName.equals("ejemplo")) {
this.in_ejemplo = false;
}else if (localName.equals("titulo")) {
this.in_titulo = false;
}else if (localName.equals("valoracion")) {
this.in_valoracion = false;
}else if (localName.equals("distancia")) {
this.in_distancia = false;
}else if (localName.equals("coordenadas")) {
this.in_coordenadas = false;
}else if (localName.equals("telefono")) {
this.in_telefono = false;
}else if (localName.equals("direccion")) {
this.in_direccion = false;
}else if (localName.equals("calle")) {
this.in_calle = false;
}else if (localName.equals("numero")) {
this.in_numero = false;
}else if (localName.equals("ciudad")) {
this.in_ciudad = false;
}else if (localName.equals("categoria")) {
this.in_categoria = false;
}
}
/** Se ejecuta cuando se encuentra con la siguiente estructura:
* <tag>characters</tag> */
@Override
public void characters(char ch[], int start, int length) {
if(this.in_titulo){
myParsedXMLDataSet.setTitulo(new String(ch, start, length));
}
if(this.in_valoracion){
myParsedXMLDataSet.setValoracion(new String(ch, start, length));
}
if(this.in_distancia){
myParsedXMLDataSet.setDistancia(new String(ch, start, length));
}
if(this.in_coordenadas){
myParsedXMLDataSet.setCoordenada(new String(ch, start, length));
}
if(this.in_telefono){
myParsedXMLDataSet.setTelefono(new String(ch, start, length));
}
if(this.in_calle){
myParsedXMLDataSet.setCalle(new String(ch, start, length));
}
if(this.in_ciudad){
myParsedXMLDataSet.setCiudad(new String(ch, start, length));
}
}
}
En la función characters se llama a las funciones que pasan los datos del Reader a la clase donde almacenamos los datos leidos, en éste caso, ParsedXMLDataSet.
ParsedXMLDataSet.java:
package com.mobiledev;
public class ParsedXMLDataSet {
private String Titulo = null;
private String Valoracion = null;
private String Distancia = null;
private String Coordenada = null;
private String Telefono = null;
private int NumCalle = 0;
private String Calle = null;
private String Ciudad = null;
private String Categoria = null;
// ===========================================================
// Getter &amp;amp;amp;amp;amp; Setter
// ===========================================================
public String getTitulo() {
return Titulo;
}
public void setTitulo(String extractedString) {
this.Titulo = extractedString;
}
public String getValoracion() {
return Valoracion;
}
public void setValoracion(String extractedString) {
this.Valoracion = extractedString;
}
public String getDistancia(){
return Distancia;
}
public void setDistancia(String extractedString){
this.Distancia = extractedString;
}
public String getCoordenada() {
return Coordenada;
}
public void setCoordenada(String extractedString) {
this.Coordenada = extractedString;
}
public String getTelefono() {
return Telefono;
}
public void setTelefono(String extractedString) {
this.Telefono = extractedString;
}
public int getNumCalle() {
return NumCalle;
}
public void setNumCalle(int extractedInt) {
this.NumCalle = extractedInt;
}
public String getCalle() {
return Calle;
}
public void setCalle(String extractedString) {
this.Calle = extractedString;
}
public String getCiudad() {
return Ciudad;
}
public void setCiudad(String extractedString) {
this.Ciudad = extractedString;
}
public String getCategoria() {
return Calle;
}
public void setCategoria(String extractedString) {
this.Categoria = extractedString;
}
public String toString(){
return "Establecimiento = " + this.Titulo
+ "\nValoracion = " + this.Valoracion
+ "\nDistancia = " + this.Distancia
+ "\nCoordenadas = " + this.Coordenada
+ "\nTelefono = " + this.Telefono
+ "\nNumCalle = " + this.NumCalle
+ "\nCalle = " + this.Calle
+ "\nCiudad = " + this.Ciudad
+ "\nCategoria = " + this.Categoria;
}
}
Ésta clase proporciona los métodos para recoger los datos del XML y un método que devuelve los valores que contiene. Éste metodo es el que se llama después de leer datos desde la clase principal y muestra los datos en el TextView. [tweetmeme]

Código fuente:
|
|
download: ParsingXML (34.39KB) added: 07/08/2009 clicks: 212 description: Ejemplo de tratamiento de ficheros XML colgados en la red. |
Entradas relacionadas:
La comunidad de desarrollo sobre Android e iPhone en castellano es algo limitada, así que hay que sumar, desde aqui intentaré aportar mi granito de arena y ayudar a quien lo necesite. No dudes en preguntar cualquier duda, entre todos los solucionaremos.
4 Comentarios to Tratamiento de ficheros XML con Android
Miguel
Abril 16th, 2010 at 5:36 PM
No consigo que me lea los caracteres con acento, cada vez que lee uno la aplicación casca
Miguel
Abril 20th, 2010 at 4:06 PM
Solucionado:
InputSource is = new InputSource(url.openStream());
is.setEncoding(”ISO-8859-1″);
xr.parse(is);
ParsedXMLDataSet parsedExampleDataSet = myXMLHandler.getParsedData();
Alfonso
Mayo 11th, 2010 at 2:06 PM
Una pregunta: Como se haría para recorrer apropiadamente el XML si en el existieran estructuras repetidas. Por ejempo
Alfonso
Mayo 11th, 2010 at 2:49 PM
Una pregunta: Como se haría para recorrer apropiadamente el XML si en el existieran estructuras repetidas. Por ejempo
*listas*
*listaCompra name=”Erosky”*
*artículo name=”tomates”*
*/articulo*
*artículo name=”aceite”*
*/articulo*
*/listaCompra*
*listaCompra name=”Carrefour”*
*artículo name=”pan”*
*/articulo*
*artículo name=”jamon”*
*/articulo*
*/listaCompra*
*/listas*