Alternativas para leer y escribir XML (y otros ficheros) en Android

Un artículo rápido antes de seguir con más temas del Curso de Programación Android.

Hace 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) ficheros de este tipo. En todos los ejemplos decidí utilizar como entrada un fichero online, que obteníamos desde una determinada URL, porque pensé que sería el caso más típico que íbamos a necesitar en la mayoría de aplicaciones. Sin embargo, desde entonces han sido muchas las consultas que me han llegado relativas a cómo utilizar estos métodos para leer un fichero XML que se encuentre en un recurso local. Adicionalmente también he recibido muchos comentarios consultando las alternativas existentes para escribir ficheros XML. Pues bien, aunque las alternativas son muchas, voy a dedicar este pequeño artículo a intentar resolver ambas dudas.

Escribir ficheros XML en Android

Para escribir ficheros XML sin meternos en muchas complicaciones innecesarias se me ocurren básicamente dos formas. La primera de ellas, y la más sencilla y directa, es construir manualmente el XML utilizando por ejemplo un objeto StringBuilder y tras esto escribir el resultado a un fichero en memoria interna o externa tal como ya vimos en los artículos dedicados a tratamiento de ficheros (I y II). Esto quedaría de una forma similar a la siguiente:

//Creamos un fichero en la memoria interna
OutputStreamWriter fout =
	new OutputStreamWriter(
		openFileOutput("prueba.xml",
			Context.MODE_PRIVATE));

StringBuilder sb = new StringBuilder();

//Construimos el XML
sb.append("");
sb.append("" + "Usuario1" + "");
sb.append("" + "ApellidosUsuario1" + "");
sb.append("");

//Escribimos el resultado a un fichero
fout.write(sb.toString());
fout.close();

Como método alternativo también podemos utilizar el serializador XML incluido con la API XmlPull. Aunque no es un método tan directo como el anterior no deja de ser bastante intuitivo. Los pasos para conseguir esto serán crear el objeto XmlSerializer, crear el fichero de salida, asignar el fichero como salida del serializador y construir el XML mediante los métodos startTag(), text() y endTag() pasándoles los nombres de etiqueta y contenidos de texto correspondientes (aunque existen más métodos, por ejemplo para escribir atributos de una etiqueta, éstos tres son los principales). Finalmente deberemos llamar a endDocument() para finalizar y cerrar nuestro documento XML. Un ejemplo equivalente al anterior utilizando este método sería el siguiente:

//Creamos el serializer
XmlSerializer ser = Xml.newSerializer();

//Creamos un fichero en memoria interna
OutputStreamWriter fout =
	new OutputStreamWriter(
		openFileOutput("prueba_pull.xml",
			Context.MODE_PRIVATE));

//Asignamos el resultado del serializer al fichero
ser.setOutput(fout);

//Construimos el XML
ser.startTag("", "usuario");

ser.startTag("", "nombre");
ser.text("Usuario1");
ser.endTag("", "nombre");

ser.startTag("", "apellidos");
ser.text("ApellidosUsuario1");
ser.endTag("", "apellidos");

ser.endTag("", "usuario");

ser.endDocument();

fout.close();

Así de sencillo, no merece la pena complicarse la vida con otros métodos más complicados.


Leer ficheros XML en Android desde recursos locales

Para leer ficheros XML desde un recurso local se me ocurren varias posibilidades, por ejemplo leerlo desde la memoria interna/externa del dispositivo, leer un XML desde un recurso XML (carpeta /res/xml), desde un recurso Raw (carpeta /res/raw), o directamente desde la carpeta /assets de nuestro proyecto. Salvo en el segundo caso (recurso XML), en todos los demás la solución va a pasar por conseguir una referencia de tipo InputStream (os recuerdo que cualquiera de los métodos que vimos para leer un XML partían de una referencia de este tipo) a partir de nuestro fichero o recurso XML, sea cual sea su localización.

Así, por ejemplo, si el fichero XML está almacenado en la memoria interna de nuestro dispositivo, podríamos acceder a él mediante el método openFileInput() tal como vimos en los artículos dedicados a tratamiento de ficheros. Este método devuelve un objeto de tipo FileInputStream, que al derivar de InputStream podemos utilizarlo como entrada a cualquiera de los mecanismos de lectura de XML (SAX, DOM, XmlPull).

//Obtenemos la referencia al fichero XML de entrada
FileInputStream fil = openFileInput("prueba.xml");

//DOM (Por ejemplo)
DocumentBuilderFactory factory =
    DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(fil);

//A partir de aquí se trataría el árbol DOM como siempre.
//Por ejemplo:
Element root = dom.getDocumentElement();

//...

En el caso de encontrarse el fichero como recurso Raw, es decir, en la carpeta /res/raw, tendríamos que obtener la referencia al fichero mediante el método getRawResource() pasándole como parámetro el ID de recurso del fichero. Esto nos devuelve directamente el stream de entrada en forma de InputStream.

//Obtenemos la referencia al fichero XML de entrada
InputStream is = getResources().openRawResource(R.raw.prueba);

//DOM (Por ejemplo)
DocumentBuilderFactory factory =
    DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(is);

//A partir de aquí se trataría el árbol DOM como siempre.
//Por ejemplo:
Element root = dom.getDocumentElement();

//...

Por último, si el XML se encontrara en la carpeta /assets de nuestra aplicación, accederíamos a él a través del AssetManager, el cual podemos obtenerlo con el método getAssets() de nuestra actividad. Sobre este AssetManager tan sólo tendremos que llamar al método open() con el nombre del fichero para obtener una referencia de tipo InputStream a nuestro XML.

//Obtenemos la referencia al fichero XML de entrada
AssetManager assetMan = getAssets();
InputStream is = assetMan.open("prueba_asset.xml");

//DOM (Por ejemplo)
DocumentBuilderFactory factory =
    DocumentBuilderFactory.newInstance();

DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(is);

//A partir de aquí se trataría el árbol DOM como siempre.
//Por ejemplo:
Element root = dom.getDocumentElement();

//...

El último caso, algo distinto a los anteriores, pasaría por leer el XML desde un recurso XML localizado en la carpeta /res/xml de nuestro proyecto. Para acceder a un recurso de este tipo debemos utilizar el método getXml() al cual debemos pasarle como parámetro el ID de recurso del fichero XML. Esto nos devolverá un objeto XmlResourceParser, que no es más que un parser de tipo XmlPull como el que ya comentamos en su momento. Por tanto, la forma de trabajar con este parser será idéntica a la que ya conocemos, por ejemplo:

//Obtenemos un parser XmlPull asociado a nuestro XML
XmlResourceParser xrp = getResources().getXml(R.xml.prueba);

//A partir de aquí utilizamos la variable 'xrp' como
//cualquier otro parser de tipo XmlPullParser. Por ejemplo:

int evento = xrp.getEventType();

if(evento == XmlPullParser.START_DOCUMENT)
	Log.i("XmlTips", "Inicio del documento");

//...

Por último, indicar que todas estas formas de acceder a un fichero en Android no se limitan únicamente a los de tipo XML, sino que pueden utilizarse para leer cualquier otro tipo de ficheros.

Como siempre, podéis descargar el código fuente completo de un sencillo programa de ejemplo que utiliza cada una de las alternativas comentadas.

, , , , , , , ,

15 Respuestas a Alternativas para leer y escribir XML (y otros ficheros) en Android

  1. JLuis 04/02/2012 at 8:36 #

    Que tal, buen ejemplo amigo, me gustaría si puedo utilizar este método para leer un xml que obtengo de un web service el cual contiene tablas y como podría aplicarlo, ya tengo todo únicamente me falta poder cargar y mostrar el xml sobre la app en Android, de antemano gracias.

  2. Hector 12/03/2012 at 0:26 #

    me uno al comentario de JLuis. necesito hacer los mismo, descargar un un achivo xml obtenido desdeun web service para luego utilizarlo como base de datos (en caso de no tener conección a internet)

  3. juliostyle77 14/03/2012 at 21:10 #

    me uno a ustedes dos, necesito lo mismo.

  4. admin 14/03/2012 at 21:24 #

    El curso incluye 3 artículos sobre como descargar y procesar un XML desde una URL de internet, y otros 2 sobre como interactuar con servicios web REST y SOAP. Todo ello unido a este artículo debería ser suficiente para resolver vuestras dudas. En caso contrario, os animaría a exponer vuestro problema en el foro de la web, para que también puedan ayudaros otros lectores. Saludos.

  5. Guillem 08/04/2012 at 19:49 #

    Yo para escribir en ficheros xml y leerlos uso la librería http://simple.sourceforge.net/ realmente cuando le pillas el truco te permite introducir nuevas variables y leerlas muy fácilmente.

  6. david 24/04/2012 at 13:20 #

    muchas gracias por todos los tutoriales que publicas, son de gran ayuda

  7. Mario Adrián Domínguez 15/05/2012 at 8:55 #

    Buenas Salvador.

    He estado ojeando y me preguntaba si es posible que pusieras algún ejemplo para JSON, ya que parece que consume mucho menos recursos.

    Saludos.

  8. Javier 25/05/2012 at 12:25 #

    Hola a todos.

    Os escribo para ver si me ayudáis con un problema.

    YO necesito descargar un fichero xml desde una url, hasta ahí todo bien, el problema viene si tengo problemas por ejemplo de conexión, y la descarga falla, entonces necesito leerlo desde un fichero en la carpeta assets, o raw, me da igual.

    El problema es que en la clase donde hago esto, descargo el fichero y lo parseo, no es hereda de Activity entonces las propuestas aki presentes para leer desde estas carpetas no me funciona. Ayuda!!

    Con heredar de activity no vale habría que tener tb el método onCreate, ye so ya no lo quiero hacer.

    Gracias!

  9. REVS 21/09/2012 at 15:08 #

    Hola sgoliver, algún momento has pensado en hacer algún ejemplo utilizando JSON? (Lectura y Escritura)

  10. Yerlak 06/02/2013 at 22:42 #

    Te felicito, un gran tutorial. Nos podrías facilitar el código completo para la parte de parseo en Raw? Ya que traté de guiarme del ejemplo DOM que pusiste unos artículos atrás y no me sirvió por unos errores. Te lo agradecía un mundo. Saludos.

  11. admin 07/02/2013 at 23:55 #

    Hola Yerlak, ¿qué error te da?

  12. Yerlak 08/02/2013 at 3:36 #

    El eclipse me marca varios, le doy para que importe librerías que faltan y no lo hace. No sé que pueda ser.
    El proyecto que hiciste de android-xml-tips no me lanza nungún error. Yo debo implementar el de “leer xml desde raw”, pero no pude completar el código para tratar el árbol dom en esa parte.
    Te mandé un correo explicándote el caso. Ando desesperado respecto a esto =S

  13. Kevin 22/03/2013 at 7:22 #

    Me gustaria que me respondieras como podria hacer un aplicativo que me permitiera generar archivos doc, xls y odt escribiendo desde el emulador. gracias por responderme.

  14. Fernando Martinez 02/04/2013 at 22:43 #

    Hola que tal me parece muy interesante tu blog ya que abordas temas que me han sido de mucha ayuda, en esta ocasión te escribo para hacerte una consulta ya que necesito generar un archivo xml, mas sin embargo no logro crear el archivo en la manera que comentas, ya que mi aplicación esta compuesta por varios packages en eclipse, y pues el package que quiero genere el archivo no me lo genera, ya que en el directorio /data/data solo me aparece la carpeta de un solo package (y no el que requiero que cree el archivo), sabes que puedo realizar al respecto???…

Trackbacks/Pingbacks

  1. Desarrollo en Android | sgoliver.net blog - 23/01/2012

    [...] [...]

Deja un comentario

Powered by WordPress. Designed by Woo Themes