En este video te explicamos en detalle todo el proceso para publicar una Aplicación Android…
Proyecto tratamiento XML en Android utilizando DOM (I)
4.
Proyecto tratamiento XML en Android utilizando DOM (I)
Siguiendo con el tratamiento de ficheros XML en Android, vamos a desarrollar una Aplicación que nos servirá como ejemplo práctico de gestión y ‘parseo’ de un documento XML utilizando el método DOM.
Al proyecto Android lo denominaremos «ParsearXML» y nos permitirá crear un sistema de ficheros XML que contienen los registros de clientes de una empresa, pudiendo realizar diferentes operaciones sobre ellos.
Visión general de la App Android «ParsearXML»
Aunque podrás ver esta Aplicación en funcionamiento en un próximo video de esta serie, mostramos aquí las dos pantallas que la componen, además de la splash de inicio. Como es habitual, el diseño es esquemático ya que nos centramos en la funcionalidad que tiene la App con las diferentes opciones para crear o cargar un XML:
Elementos del Proyecto Android
Comenzaremos enumerando los elementos necesarios para el desarrollo de este proyecto denominado «ParsearXML»:
- Clase SplashScreen, que hereda de la clase base Activity, encargada de lanzar una pantalla de presentación al iniciar la aplicación, proporcionando una mayor inmersión del usuario en la aplicación.
- Clase MainActivity, que hereda de la clase base Activity, y que permitirá introducir la información del cliente en un nodo del documento XML.
- Clase TareasXML, que herede de la clase base ListActivity, encargada de mostrar el contenido del documento almacenado en memoria interna del dispositivo, seleccionado por el usuario.
- Clase Adaptador, que hereda de la clase base BaseAdapter, encargado de construir la vista de cada uno de los ítem que se mostrará en el componente ListView.
- Clase Cliente, que definirá el constructor con los argumentos para la creación de un nuevo objeto Cliente, además de los métodos de acceso getter y setter para las propiedades privadas.
- Clase ParsearDOM, cuya tarea principal será la de parsear el documento XML, para a continuación construir en memoria un nuevo documento con toda la información.
- Clase TareaAsincronaListado, que hereda de la clase AsyncTask, y que permitirá cargar en segundo plano toda la información del documento XML en memoria, para posteriormente mostrarla por pantalla.
- Layout
activity_splash_screen.xml
, formado por una componente de tipo ImageView, que mostrará el logotipo de la aplicación. - Layout
activity_main.xml
, formado por cuatro controles de tipo EditText que permitirán al usuario introducir los datos del cliente, y tres controles de tipoButton
, encargados de omitir, eliminar o crear una nueva ficha de cliente. - Layout
activity_tareasxml.xml
, formado por un controlListView
, que mostrará el contenido del archivo XML seleccionado por el usuario, un controlSpinner
con los documentos almacenados en la memoria interna del dispositivo , y tres controles de tipoButton
para cargar el XML seleccionado, filtrar el resultado que se muestra por el valor introducido en el controlEditText
, y actualizar la información en pantalla. - Layout
item.xml
, que definirá la vista personalizada de cada ítem que construya el controlListView
.
Estructura del proyecto
Puedes ver la estructura del proyecto en la siguiente imagen:
Documentación código fuente
Detallamos las diferentes clases y métodos que definimos en el proyecto, así como los ficheros de layout y controles que implementan. Hemos dividido la publicación del proyecto en dos partes. En esta primera veremos en detalle las clases:
- MainActivity.ja
- TareasXML.java
y en la siguiente publicación, completaremos con el resto de clases y ficheros de layout. Allí también podrás descargar (usuarios Premium) todo el código del proyecto.
ParsearXML\app\src\main\java\com\academiaandroid\parsearxml\MainActivity.java
Se define la clase MainActivity
, que hereda de la clase base Activity
, y que permite crear un archivo XML con una estructura de etiquetas concreta, y añadir el contenido introducido por el usuario:
1 2 |
public class MainActivity extends Activity { |
Posteriormente, dentro del método onCreate(), se define toda la lógica de eventos de usuario, desde la que se podrá crear una nueva ficha de cliente, a omitir cualquier operación y pasar a la siguiente Activity. Además se referencian los diferentes tipos de variables (EditText
, TextView
y Button
) con sus controles a nivel de layout:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
@Override protected void onCreate(Bundle savedInstanceState) { [...] edNombre = (EditText)findViewById(R.id.edNombre); edApellido = (EditText)findViewById(R.id.edApellido); edCuenta = (EditText)findViewById(R.id.edCuenta); edTelefono = (EditText)findViewById(R.id.edTelefono); tvDocumentoSeleccionado = (TextView) findViewById(R.id.tvDocumentoSeleccionado); btnBorrar = (Button)findViewById(R.id.btnBorrar); btnNuevoCliente = (Button)findViewById(R.id.btnNuevoCliente); btnOmitir = (Button)findViewById(R.id.btnOmitir); [...] btnBorrar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { if (borrarFicha(tvDocumentoSeleccionado.getText().toString())) { Toast.makeText(MainActivity.this, "Cliente con nº de cuenta: " + edCuenta.getText().toString() + " eliminado.", Toast.LENGTH_LONG).show(); Intent intent = new Intent(MainActivity.this, TareasXML.class); startActivity(intent); finish(); } }catch(Exception ex) { Toast.makeText(MainActivity.this, "No se ha eliminado el cliente: " + ex.getMessage(), Toast.LENGTH_LONG).show(); } } }); btnNuevoCliente.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { if(edNombre.getText().toString().equals("") && edApellido.getText().toString().equals("") && edCuenta.getText().toString().equals("") && edTelefono.getText().toString().equals("")) { Toast.makeText(MainActivity.this, "Debe indicar todos los datos del nuevo cliente.", Toast.LENGTH_LONG).show(); }else { crearXML(edNombre.getText().toString(), edApellido.getText().toString(), edCuenta.getText().toString(), edTelefono.getText().toString(),fechaActual()); } { Intent intent = new Intent(MainActivity.this, TareasXML.class); startActivity(intent); finish(); Toast.makeText(MainActivity.this, "Nuevo cliente creado: " + edCuenta.getText().toString(), Toast.LENGTH_LONG).show(); } }catch(Exception ex) { Toast.makeText(MainActivity.this, "Excepción al crear nuevo cliente: " + ex.getMessage(), Toast.LENGTH_LONG).show(); } } }); btnOmitir.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, TareasXML.class); startActivity(intent); } }); } |
Como parte fundamental de esta clase, nos encontramos con el método crearXML()
, que recibirá como argumentos de entradas los datos introducidos por el usuario por pantalla (además de la fecha de creación del documento), y que construye la lógica de nodos del documento XML:
Ya comentamos en la publicación anterior que otra forma muy válida para el parseo de un documento XML es el método XmlPull, de grandes similitudes al método StAX (Streaming API for XML), y por extensión al modelo SAX, ya que realiza una lectura secuencial a partir de los eventos y acciones definidas. En este método crearXML() hacemos uso de la interfaz XmlSerializer del paquete org.xmlpull.v1 para la creación de un documento XML (documentación de las diferentes interfaces y métodos que implementa esta API).
1 2 3 4 5 6 |
public void crearXML(String nombre, String apellido, String cuenta, String telefono, String fecha) { try { File archivoXML = new File("cliente_" + fecha + ".xml"); |
XmlSerializer
, que permitirá serializar la información del documento XML:
1 2 3 4 |
XmlSerializer xmlSerializer = Xml.newSerializer(); OutputStreamWriter osWriter = new OutputStreamWriter(openFileOutput(archivoXML.getName().toString(), Context.MODE_APPEND)); xmlSerializer.setOutput(osWriter); |
1 2 |
xmlSerializer.startDocument("utf-8", false); |
1 2 3 |
xmlSerializer.startTag("", "Clientes"); xmlSerializer.startTag("", "Cliente"); |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
xmlSerializer.startTag("", "Nombre"); xmlSerializer.text(nombre); xmlSerializer.endTag("", "Nombre"); xmlSerializer.startTag("", "Apellido"); xmlSerializer.text(apellido); xmlSerializer.endTag("", "Apellido"); xmlSerializer.startTag("", "Cuenta"); xmlSerializer.text(cuenta); xmlSerializer.endTag("", "Cuenta"); xmlSerializer.startTag("", "Telefono"); xmlSerializer.text(telefono); xmlSerializer.endTag("", "Telefono"); |
1 2 3 |
xmlSerializer.endTag("", "Cliente"); xmlSerializer.endTag("", "Clientes"); |
1 2 3 4 5 6 7 8 9 10 11 12 |
xmlSerializer.endDocument(); osWriter.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } |
ParsearXML\app\src\main\java\com\academiaandroid\parsearxml\TareasXML.java
Se define una nueva clase llamada TareasXML
, que hereda de la clase base ListActivity
, encargada de mostrar los documentos XML creados y leer/filtrar el documento seleccionado en un control ListView
:
1 2 |
public class TareasXML extends ListActivity { |
Dentro del método onCreate()
, se asocian las variables de tipo EditText
, ListView
, Spinner
y Button
con sus recursos a nivel de layout. Además se define la lógica de selección de un documento XML para ser leído y mostrado a través del control ListView
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Override protected void onCreate(Bundle savedInstanceState) { [...] edFiltroResultado = (EditText)findViewById(R.id.edFiltroResultado); imbtnActualizar = (ImageButton)findViewById(R.id.imbtnActualizar); btnCargarDocumento = (Button)findViewById(R.id.btnCargarDocumento); btnFiltrarResultados = (Button)findViewById(R.id.btnFiltrarResultados); btnNuevo = (Button)findViewById(R.id.btnNuevo); spDoc = (Spinner)findViewById(R.id.spDoc); |
Se comprueba que el método listarDoc()
no devuelva null
para llenar el control Spinner
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
if(listarDoc() != null) { ArrayAdapter<String> adapter = new ArrayAdapter<String>(TareasXML.this, android.R.layout.simple_spinner_item,listarDoc()); spDoc.setAdapter(adapter); } btnNuevo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(TareasXML.this, MainActivity.class); intent.putExtra("documento", spDoc.getSelectedItem().toString()); startActivity(intent); finish(); } }); lvClientes = (ListView)findViewById(android.R.id.list); lvClientes.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(TareasXML.this, MainActivity.class); String archivo = spDoc.getSelectedItem().toString(); try { intent.putExtra("documento", spDoc.getSelectedItem().toString()); intent.putExtra(NODE_NOMBRE, new TareaAsincronaListado(TareasXML.this).execute(archivo).get().get(position).getNombre().toString());//listadoDocumento(listarDoc().get(position).toString()).get(position).getNombre().toString()); intent.putExtra(NODE_APELLIDO, new TareaAsincronaListado(TareasXML.this).execute(archivo).get().get(position).getApellido().toString());//listadoDocumento(listarDoc().get(position).toString()).get(position).getApellido().toString()); intent.putExtra(NODE_CUENTA, new TareaAsincronaListado(TareasXML.this).execute(archivo).get().get(position).getCuenta().toString());//listadoDocumento(listarDoc().get(position).toString()).get(position).getCuenta().toString()); intent.putExtra(NODE_TELEFONO, new TareaAsincronaListado(TareasXML.this).execute(archivo).get().get(position).getTelefono().toString());//listadoDocumento(listarDoc().get(position).toString()).get(position).getTelefono().toString()); startActivity(intent); finish(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }); imbtnActualizar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onCreate(new Bundle()); } }); btnCargarDocumento.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String archivo = spDoc.getSelectedItem().toString(); try { if(!archivo.equals("") || archivo != null) { lvClientes.setAdapter(new Adaptador(TareasXML.this, new TareaAsincronaListado(TareasXML.this).execute(archivo).get())); } } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }); btnFiltrarResultados.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(buscarEnDocumento(edFiltroResultado.getText().toString(), spDoc.getSelectedItem().toString()) != null) { lvClientes.setAdapter(new Adaptador(TareasXML.this, buscarEnDocumento(edFiltroResultado.getText().toString(),spDoc.getSelectedItem().toString()))); }else { Toast.makeText(TareasXML.this,"Sin resultados para la búsqueda: " + edFiltroResultado.getText().toString(),Toast.LENGTH_LONG).show(); } } }); } |
El método buscarEnDocumento()
posibilita filtrar el resultado del contenido del documento seleccionado por el usuario. Esta característica es de gran utilidad para documentos extensos:
1 2 3 4 5 6 |
public List<Cliente> buscarEnDocumento(String filtro,String documento) { parser = new ParsearDOM(this); try { stream = openFileInput(documento); doc = parser.getDocument(stream); |
Se obtiene los elementos por Cliente:
1 2 |
NodeList nodeList = doc.getElementsByTagName(NODE_CLIENTE); |
Se inicializa una variable de tipo List
que almacenará objetos de tipo Cliente:
1 2 3 4 5 6 |
arrayClientes = new ArrayList<Cliente>(); for (int i = 0; i < nodeList.getLength(); i++) { Element e = (Element) nodeList.item(i); |
Se comprueba por cada iteración si el valor de búsqueda introducido por el usuario coincide con cualquiera de los campos de la ficha del cliente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
if(parser.getValue(e,NODE_NOMBRE).trim().equals(filtro) || parser.getValue(e,NODE_APELLIDO).trim().equals(filtro) || parser.getValue(e,NODE_CUENTA).trim().equals(filtro) || parser.getValue(e,NODE_TELEFONO).trim().equals(filtro)) { Cliente cliente = new Cliente(parser.getValue(e,NODE_NOMBRE), parser.getValue(e,NODE_APELLIDO), parser.getValue(e,NODE_CUENTA), parser.getValue(e,NODE_TELEFONO)); arrayClientes.add(cliente); } } Toast.makeText(this,"Número de resultados: " + arrayClientes.size(),Toast.LENGTH_LONG).show(); } catch (Exception ex) { ex.printStackTrace(); } return arrayClientes; } |
En la siguiente publicación veremos las clases:
- TareaAsincronaListado.java
- ParsearDOM.java
y los diferentes ficheros de layout:
- activity_main.xml
- activity_tareasxml.xml
- item.xml
Esta entrada tiene un comentario
Los comentarios están cerrados.
[…] 4.Proyecto tratamiento XML en Android utilizando DOM (I) […]