Tratamiento de XML en Android: DOM
Siguiendo con el tratamiento de información XML en Android y tras describir el modelo SAX en la anterior publicación, vamos a presentar en ésta el modelo DOM.
Definición de DOM (Document Object Model)
DOM es el acrónimo de Modelo del Objeto Documento. El DOM, representa al documento XML y sus diferentes partes en una especie de organigrama con un conjunto de nodos dispuestos de forma jerárquica. Estos nodos son los elementos del documento, y se compara de forma habitual con la imagen de un árbol que se va ramificando en distintos niveles y en donde las hojas son los elementos o nodos que tiene la página.
Si has programado alguna vez páginas web (X)HTML quizás sabrás que el DOM es una API (Interfaz de Programación de Aplicaciones), es decir nos proporciona un conjunto de métodos que nos permiten acceder a cada uno de esos nodos o elementos, pudiendo modificarlos, eliminarlos o incluso crear nuevos utilizando algún lenguaje de programación. En la web es muy común utilizar Javascript, pero la API del DOM es independiente del lenguaje, y en este entorno Android utilizaremos lógicamente Java.
De esta forma, el DOM representa un modelo abstracto del documento XML como un mapa de nodos conectados que carga completamente en memoria, donde cada nodo es un objeto que podemos manipular mediante un programa, con la potencia que esto implica, aunque también con el consumo de recursos asociado, por ejemplo si se trata con un fichero XML muy extenso.
Veamos un sencillo simplificado de un fichero XML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version='1.0' encoding='utf-8' standalone='no' ?> <Clientes> <Cliente> <Nombre>Nombre1</Nombre> <Apellido>Apellido1</Apellido> <Cuenta>0001</Cuenta> <Telefono>012345678</Telefono> </Cliente> <Cliente> <Nombre>Nombre2</Nombre> <Apellido>Apellido2</Apellido> <Cuenta>0002</Cuenta> <Telefono>876543210</Telefono> </Cliente> .............. </Clientes> |
y su representación gráfica en forma de mapa de nodos organizados jerárquicamente (pincha en la imagen para ampliarla):
Interfaces y Métodos DOM (paquete Java org.w3c.dom.*)
En este apartado, vamos a describir los principales interfaces y métodos que intervienen en la gestión de nodos del paquete Java org.w3c.dom.*
.
Al final del mismo, mostraremos un ejemplo sencillo de utilización de algunos de esos métodos sobre un documento XML muy básico y en la próxima publicación veremos un proyecto ejemplo más completo.
org.w3c.dom.*
Paquete donde se definen todas las clases e interfaces que permitirán manipular desde Java los nodos de un documento (documentación oficial en Android Developers XML)
org.w3c.dom.Document
Interfaz Document
que representa la totalidad de un documento HTML o XML.
Interfaces DOM |
Element |
Node |
Nodelist |
Attr |
org.w3c.dom.Element
Interfaz Element
que proporciona la abstracción de un conjunto ordenado de nodos, sin definir o limitar cómo se implementa esta colección.
Métodos públicos | |
Método | Descripción |
getAttribute(String name) | Devuelve el valor del atributo pasándole como argumento el nombre. |
getAttributeNode(String name) | Devuelve el nodo del atributo pasándole como argumento el nombre. |
getElementsByTagName(String name) | Devuelve un NodeList de todos los elementos descendientes del atributo, pasándole como argumento el nombre de la etiqueta. |
getTagName() | Devuelve el nombre del elemento. |
removeAttribute(String name) | Elimina un atributo por su nombre. |
org.w3c.dom.Node
Interfaz Node
que define el tipo de dato primario para todo el DOM. Esto permite ser representado como un solo nodo en el árbol del documento.
Métodos públicos | |
Método | Descripción |
getFirstChild() | Devuelve el primer nodo hijo del nodo actual. Si no existe, devuelve null. |
getNextSibling() | Devuelve el nodo inmediatamente siguiente (hermano) a este nodo. Si no existe, devuelve null. |
getParentNode() | Devuelve el padre de este nodo. Todos los nodos, excepto los de tipo Attr, Document, DocumentFragment, Entity, y Notation pueden tener un padre. Sin embargo, será null si el nodo está recién creado y no ha sido añadido todavía al árbol, o si ha sido eliminado del árbol. |
getChildNodes() | Devuelve una lista de la clase NodeList que contiene todos los nodos hijo de este nodo. En caso de que no haya nodos hijos, la lista estará vacía. |
removeChild(Node oldChild) | Elimina el nodo indicado como argumento de entrada. |
replaceChild(Node newChild, Node oldChild) | Reemplaza el nodo hijo existente (oldChild) por un nuevo nodo (newChild). |
appendChild(Node newChild) | Añade un nuevo nodo al final de la lista de hijos de este nodo. |
insertBefore(Node newChild, Node refChild) | Inserta un nuevo nodo (newChild) antes del nodo hijo existente (refChild). |
org.w3c.dom.NodeList
Interfaz NodeList
que permite la abstracción de un conjunto ordenado de nodos, sin definir o limitar cómo se implementa esta colección. Los elementos de la interfaz NodeList
son accesibles a través de un índice, comenzando desde 0.
Métodos públicos | |
Método | Descripción |
getLength() | Devuelve el número de nodos en la lista. |
item(int index) | Devuelve el índice del elemento de la colección. |
org.w3c.dom.Attr
Interfaz Attr
que representa un atributo dentro de un objeto Element. No son considerados por DOM como parte de la estructura del documento, al no tratarse de nodos hijos del elemento que describen.
Métodos públicos | |
Método | Descripción |
getName() | Devuelve el nombre del atributo. |
getOwnerElement() | Recupera el Element propietario del atributo. |
getValue() | Devuelve un String con el valor del atributo. |
Ejemplo básico uso métodos DOM
Vamos a tratar este sencillo fichero XML:
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version='1.0' encoding='utf-8' standalone='no' ?> <Clientes> <Cliente> <Nombre>Nombre1</Nombre> <Apellido>Apellido1</Apellido> <Cuenta>0001</Cuenta> <Telefono>012345678</Telefono> </Cliente> </Clientes> |
con el siguiente código, que nos servirá como un ejemplo básico del uso de algunas de estas interfaces y métodos presentados:
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 |
[...] try { InputStream stream = null; Document document = null; Node nodo; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder db = factory.newDocumentBuilder(); //El archivo XML debe estar situado en la ruta 'data/data/package/files/cliente_21_16_20_11_2015.xml' stream = openFileInput("cliente_21_16_20_11_2015.xml"); InputSource inputSource = new InputSource(stream); document = db.parse(inputSource); NodeList nodeList = document.getElementsByTagName("Cliente"); //Muestra el número de nodos hijos del nodo raíz. System.out.println("Nº Nodos hijos: " + String.valueOf(nodeList.getLength())); for (int i = 0; i < nodeList.getLength(); i++) { Element e = (Element) nodeList.item(i); //Devuelve el nodo principal del documento. System.out.println("Nodo raíz o padre: " + e.getParentNode().getNodeName()); nodo = nodeList.item(i); //Devuelve el primer nodo hijo del nodo raíz. System.out.println("Nodos hijos: " + nodo.getParentNode().getFirstChild().getNodeName()); //Devuelve el primer nodo final del nodo Cliente. System.out.println("Primer nodo hijo de Cliente: " + nodo.getFirstChild().getNodeName()); //Contenido texto nodo final Nombre. System.out.println("Texto nodo Nombre: " + nodo.getFirstChild().getTextContent()); //Devuelve el contenido de los nodos finales. System.out.println("Texto nodos finales: " + nodo.getTextContent()); System.out.println("Nodo a eliminar: " + nodo.getNodeName()); e.removeChild(nodo); e.normalize(); } }catch(Exception ex) { System.out.println("Error: " + ex.getMessage()); } [...] |
Si compilamos el código anterior, se mostraría la siguiente salida a través del logcat de Android Studio:
En las próximas publicaciones (tutorial web con código descargable y video) desarrollaremos un proyecto donde crearemos un sistema de ficheros XML para las fichas de clientes de una empresa, pudiendo realizar diferentes operaciones sobre dicha información.