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.
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.
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:
17 comentarios
[…] […]
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.
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)
me uno a ustedes dos, necesito lo mismo.
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.
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.
muchas gracias por todos los tutoriales que publicas, son de gran ayuda
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.
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!
Hola sgoliver, algún momento has pensado en hacer algún ejemplo utilizando JSON? (Lectura y Escritura)
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.
Hola Yerlak, ¿qué error te da?
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
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.
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???…
Mi movil no esta rooteado y no puedo acceder al xml creado en el emulador, pordrias describir cual es la estructura exacta que se genera al crear el xml. Muchas gracias por la ayuda.
Yo tengo un problema, estoy creando un xml como lo dice el tutorial solo que estoy metiendo atributos, el problema es que al querer leer los atributos con el metodo DOM que viene aqui en el curso, me arroja «null» en donde deberian de ir los atributos, ya cheque bien y aun asi me sigue arrojando esto, seia posible ver un ejemplo donde se manejen los atributos?