9 DOM¶
Introducción¶
DOM (Document Object Model) es una API de Java que te permite manipular documentos XML de forma jerárquica, estructurada y en memoria.
DOM se encarga de representar el contenido XML como un árbol de nodos en memoria, siendo cada elemento (etiqueta) un nodo del árbol.
De esta forma, se puede leer, modificar, agregar o eliminar partes de un XML mediante métodos Java.
Fichero XML con DOM¶
Para crear un fichero XML haciendo uso de la API de DOM, necesitamos crear un objeto que se encargue de cargar (parsear) el fichero XML y convertirlo en un árbol de nodos.
A través de la clase DocumentBuilder
, creamos dicho objeto. El problema está que dicha clase, no permite usar el constructor, por lo que debemos usar una clase que se encargue de crear estos tipos de objetos haciendo uso del patrón factory. La clase DocumentBuilderFactory
es la clase que se encarga de ello.
A través del método newDocument()
de la clase DocumentBuilder
podemos crear un objeto de tipo documento que simulará el árbol de nodos.
Veamos un ejemplo:
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.newDocument();
} catch(Exception e) {
System.out.println(e.getMessage());
}
Sin embargo, si se desea cargar los nodos de un fichero XML ya existente, se usaría el método parse(File f)
:
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file);
} catch(Exception e) {
System.out.println(e.getMessage());
}
Manipular elementos¶
A través del método createElement(String name)
podemos crear un elemento de nuestro XML, y añadirlo a nuestro documento a través del método appendChild(Element e)
.
También podemos añadir, a través del mismo método, otros elementos a un elemento:
Element persona = doc.createElement("persona");
Element nombre = doc.createElement("nombre");
Element edad = doc.createElement("edad");
persona.appendChild(nombre);
persona.appendChild(edad);
root.appendChild(persona);
Esto sería similar a:
Para añadir información de texto entre las etiquetas, se utiliza la clase createTextNode(String str)
:
A través del método removeChild(Element e)
se puede eliminar un nodo y a través del método replaceChild(Element newE, Element oldE)
se puede remplazar un elemento por otro.
Atributos¶
En XML los elementos pueden tener atributos, y desde DOM podemos trabajar con ellos. Podemos crear el atributo con el método createAttribute(String attributeName)
de la clase Document
, añadir un valor con el método setValue(String value)
y añadirlo al elemento con el método setAttributeNode(Attr attribute)
de la clase Element
. Veamos un ejemplo:
Element element = doc.createElement("peso");
Attr attribute = doc.createAttribute("medida");
attr.setValue("kg");
element.setAttributeNode(attribute);
Sería algo similar a esto:
Acceso a los elementos¶
Podemos acceder a los elementos de diferente forma, dependiendo del tipo de elemento al que quiero acceder. Podemos distinguir dos tipos de elementos principales:
- Elemento raíz: Es el nodo principal de un XML, y es la primera etiqueta del mismo. El resto de elementos están contenidos en su interior.
- Elementos hijos: Son todos los nodos que están dentro de un nodo.
Todos los fichero XML tiene un elemento raíz, que es el primer elemento principal y por lo tanto el que contiene toda la información a almacenar.
Para obtener el elemento raíz, se puede usar el método getDocumentElement()
de la clase Document
:
También podemos usarlo con el método normalize()
que elimina los nodos vacíos y combina nodos adyacentes si los hubiera:
Para poder acceder a los hijos de un nodo, se puede utilizar el método getChildNodes()
que devuelve un objeto de NodeList
con una lista de los elementos hijos del nodo:
Para acceder a los elementos que tienen un nombre específico, se puede utilizar el método getElementsByTagName(String name)
que devuelve un NodeList
con todos los elementos que tengan como nombre identificativo el nombre proporcionado:
También existen otros métodos como, getFirstChild()
o getLastChild()
, que devuelve el primer o último nodo hijo de otro elemento, respectivamente.
NodeList¶
NodeList
es un interfaz del paquete org.w3c.dom
que representa una colección de nodos XML.
Es un tipo de colección inmutable, por lo que no se permite añadir más elementos a través de ella y además es de tamaño fijo, y podemos recorrerla a través de un índice.
Sus métodos más destacados:
int getLength()
: Devuelve el número de nodos que contiene la colección.Node item(int index)
: Devuelve el nodo en la posición indicada.
Node
es una interfaz que representa cualquier nodo. La clase Element
y Document
implementa dicha interfaz, por lo que podemos utilizar los métodos tanto en un Element
como en un Document
, por ejemplo appendChild()
o getElementsByTagName()
.
Información de los elementos¶
Estos son los métodos que nos permite obtener o modificar información de los elementos de un XML:
String getNodeName()
: devuelve el nombre del nodo.String getTextContent()
: devuelve el texto que contiene la etiqueta.void setTextContent(String txt)
: modifica el texto que contiene la etiqueta.
También existen métodos para acceder o modificar la información de los atributos de un elemento:
String getAttribute(String attrName)
: devuelve el valor de un atributo.void setAttribute(String attrName, String attrValue)
: crea o modifica el atributo con el valor indicado.boolean hasAttribute(String attrName)
: verifica si el atributo existe.NameNodeMap getAttributes()
: obtiene una lista de los atributos de un elemento.
NameNodeMap
es una interfaz que contiene una lista de nodos nombrados, como los atributos. Tiene diferentes métodos para acceder a ellos:
getLength()
: devuelve el número de atributos que contiene el elemento.item(int index)
: devuelve el atributo a través del indice.
Ficheros XML¶
Si quisiéramos escribir un archivo XML siguiendo la misma estructura del concesionario deberíamos instanciar nuestro documento e instanciar las clases TransformerFactory
y Transformer
, encargadas de transformar nuestro documento en un XML y DOMSource
y StreamResult
para crear el archivo.
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.newDocument();
// definimos el elemento raíz del documento
Element eRaiz = doc.createElement("concesionario");
doc.appendChild(eRaiz);
// definimos el nodo que contendrá los elementos
Element eCoche = doc.createElement("coche");
eRaiz.appendChild(eCoche);
// atributo para el nodo coche
Attr attr = doc.createAttribute("id");
attr.setValue("1");
eCoche.setAttributeNode(attr);
// definimos cada uno de los elementos y le asignamos un valor
Element eMarca = doc.createElement("marca");
eMarca.appendChild(doc.createTextNode("Renault"));
eCoche.appendChild(eMarca);
Element eModelo = doc.createElement("modelo");
eModelo.appendChild(doc.createTextNode("Megano"));
eCoche.appendChild(eModelo);
Element eCilindrada = doc.createElement("cilindrada");
eCilindrada.appendChild(doc.createTextNode("1.5"));
eCoche.appendChild(eCilindrada);
// clases necesarias finalizar la creación del archivo XML
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("ejercicio3.xml"));
transformer.transform(source, result);
} catch(Exception e) {
e.printStackTrace();
}