Diferencia entre revisiones de «Prog Tratamientos de documentos XML»

De MediaWiki
Ir a la navegación Ir a la búsqueda
 
(No se muestran 6 ediciones intermedias del mismo usuario)
Línea 15: Línea 15:
 
<syntaxhighlight lang="xml" enclose="div" highlight="" >
 
<syntaxhighlight lang="xml" enclose="div" highlight="" >
 
<?xml version="1.0" encoding="UTF-8" ?>
 
<?xml version="1.0" encoding="UTF-8" ?>
<pedidos num_pedidos="1"  fecha_pedido="10/02/2012">
+
<pedidos num_pedidos="1"  fecha_pedido="10-02-2012">
 
  <responsable>Angel Fernandez</responsable>
 
  <responsable>Angel Fernandez</responsable>
 
  <pedido>
 
  <pedido>
Línea 243: Línea 243:
  
  
 +
* Esto es debido a que al no definir un [https://www.w3schools.com/xml/xml_dtd.asp DTD], Java va a tratar los espacios en blanco/enters/tabuladores como información que debe preservar y por tanto creará un nodo asociado.
 +
: Más información [http://www.oracle.com/technetwork/articles/wang-whitespace-092897.html en este enlace].
 +
 +
 +
 +
 +
<br />
 
: <u>Ejercicio propuesto:</u> Navega manualmente hasta <productos> y obtén el valor del atributo número de productos.
 
: <u>Ejercicio propuesto:</u> Navega manualmente hasta <productos> y obtén el valor del atributo número de productos.
 
:: Después navega hasta el primer producto y obtén su código y cantidad.
 
:: Después navega hasta el primer producto y obtén su código y cantidad.
Línea 318: Línea 325:
 
             }
 
             }
 
</syntaxhighlight>  
 
</syntaxhighlight>  
 +
 +
 +
* Ejemplo de uso [http://jmoral.es/blog/xml-dom en este enlace].
 +
  
  
Línea 357: Línea 368:
  
 
: Paso dicho archivo a un árbol DOM y procésalo para crear una lista de objetos de una clase Staff creada por ti previamente.
 
: Paso dicho archivo a un árbol DOM y procésalo para crear una lista de objetos de una clase Staff creada por ti previamente.
: Ordena dicha dicha por nombre y ciudad.
+
: Ordena dicha lista por nombre y ciudad.
 
: Muestra los datos ordenados de las dos formas.
 
: Muestra los datos ordenados de las dos formas.
  
  
 
: Parte de la solución la podéis encontrar [https://stackoverflow.com/questions/14566596/loop-through-all-elements-in-xml-using-nodelist en este enlace].
 
: Parte de la solución la podéis encontrar [https://stackoverflow.com/questions/14566596/loop-through-all-elements-in-xml-using-nodelist en este enlace].
 
 
  
 
==Modificando el contenido de un árbol DOM==
 
==Modificando el contenido de un árbol DOM==
Línea 535: Línea 544:
 
     StreamResult result = new StreamResult(ficheroSalida);        // Flujo de datos usado en XML
 
     StreamResult result = new StreamResult(ficheroSalida);        // Flujo de datos usado en XML
 
     transformer.transform(source, result);
 
     transformer.transform(source, result);
        }
+
}
        catch (TransformerException ex) {
+
    catch (TransformerException ex) {
            Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
+
      Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
        }
 
 
}
 
}
 
</syntaxhighlight>  
 
</syntaxhighlight>  
Línea 569: Línea 577:
 
==Ejercicios propuestos==
 
==Ejercicios propuestos==
  
* Crea a través de código un nuevo archivo XML que refleje la estructura (con datos de ejemplo) de un correo electrónico. Se quiere guardar en qué fecha fue enviado, quién lo envía, la dirección de correo de quién lo envía, la dirección de correo de quién se envía, el mensaje, el número de archivos adjuntos y el nombre de cada uno de los archivos adjuntos (en caso de que lleve).
+
* Crea a través de código un nuevo archivo XML que refleje la estructura (con datos de ejemplo) de un correo electrónico. Se quiere guardar en qué fecha fue enviado, quién lo envía, la dirección de correo de quién lo envía, la dirección de correo de a quién se envía, el mensaje, el número de archivos adjuntos y el nombre de cada uno de los archivos adjuntos (en caso de que lleve).
  
  

Revisión actual del 09:24 28 oct 2018

Introducción

  • XML viene de Extensible Markup Language.


  • Podéis consultar la historia y uso del XML en este enlace.


  • Uno de los usos del lenguaje XML es el intercambio de información entre sistemas heterogéneos.
La información se transmite en formato texto (normalmente unicode) con una estructura en forma de etiquetas muy parecida a la conocida por todos, HTML.


  • Veamos un ejemplo de fichero XML:
<?xml version="1.0" encoding="UTF-8" ?>
<pedidos num_pedidos="1"  fecha_pedido="10-02-2012">
 <responsable>Angel Fernandez</responsable>
 <pedido>
  <id>1</id>
  <productos num_productos="2">
    <producto>
     <codigo>221</codigo>
     <cantidad>10</cantidad>
    </producto>
    <producto>
     <codigo>231</codigo>
     <cantidad>10</cantidad>
    </producto>
   </productos>
 </pedido>
</pedidos>


  • Para que un documento cumpla el estándar XML tiene que cumplir las siguientes reglas:
  • Debe de tener una cabecera donde se especifica la versión de XML que cumple el documento. También suele aparecer tipo de codificación, normalmente UTF-8 o ISO-8859-1.
  • El documento debe estar estructurado en forma de etiquetas de apertura <etiqueta> y cierre </etiqueta>.
  • Un documento debe de tener al menos una etiqueta de apertura y otra de cierre.
  • Se pueden poner etiquetas que abran y cierren la etiqueta al mismo tiempo de la forma: <etiqueta />. Por ejemplo: <representante nombre="Angel" />
  • El orden de las etiquetas es importante. Se deben cerrar en el orden inverso a como fueron abiertas.
  • Se distingue mayúsculas y minúsculas en la apertura y cierre de etiquetas.
  • Una etiqueta puede llevar uno o más atributos. Por ejemplo: <pedidos num_pedidos="10" fecha_pedido="10/01/2012">
  • No puede haber atributos con el mismo nombre en la misma etiqueta.
  • Todos los atributos deben ir entre comillas dobles.
  • Se pueden añadir comentarios de la forma:
<!-- Texto comentario -->
  • Los nombres de las etiquetas y atributos no pueden tener espacios en blanco.



  • En Java, cuando manejamos un documento XML o bien creamos uno nuevo, vamos a tener que recorrer / crear la estructura anterior.
En Java cada elemento de esa estructura recibe un nombre. Así:
  • Las etiquetas de apertura y cierre junto con su contenido se denomina Elements. En element puede tener otros 'element' en su contenido.
  • Los atributos se denominan Attr y sólo pueden existir dentro de element, en la etiqueta de apertura.
  • La información (el texto) que va entre las etiquetas de apertura y cierre se denomina Text.
  • Los comentarios pueden ir en cualquier lugar del documento y se denominan Comment.



Java: Procesando archivos XML

  • Cuando tratemos con documentos XML vamos a diferenciar dos fases:
  • Comprobar que el documento XML esté bien formado en base a las reglas que indicamos en la introducción.
  • Pasar dicho documento a un conjunto de objetos que podamos manejar desde Java. Este formato se denomina DOM (Document Object Model), modelo de objetos de documento. En DOM cada etiqueta es un nodo de una rama de un árbol jerárquico a la que vamos podemos acceder obteniendo su contenido, atributos, nombre,...
  • Tanto el estándar XML como DOM, son estándares propuesto por W3C (World Wide Web Consortium)


  • Por lo tanto vamos a pasar el documento XML en formato texto a un árbol DOM desde donde poder acceder a cada uno de los elementos del documento XML.



Pasando de documento XML a árbol DOM

  • Lo primero que tenemos que hacer es verificar que el documento XML esté bien formado. Para ello se hace uso de un parser.
  • Hay dos tipos parser:
  • Sin validación: Comprueba que el documento esté bien formado de acuerdo a las reglas de sintaxis de XML.
  • Con validación: Además de comprobar que el documento está bien formado, comprueba el documento utilizando un DTD (ya sea interno o externo). Un DTD (Document Type Definition) es un documento en el que se indica cual es la estructura que tiene que tener el documento, sus elementos y atributos.
  • Nosotros vamos a hacer uso de un parser sin validación que además va a ser compatible con el modelo de objeto de documento (DOM) de XML


  • Vamos a hacer uso de las siguientes clases:


  • Los pasos a seguir son los siguientes:
 1     public static void main(String[] arg){
 2         
 3         try {
 4             // Construimos nuestro DocumentBuilder
 5             DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 6             // Procesamos el fichero XML y obtenemos nuestro objeto Document
 7             Document doc = documentBuilder.parse(new File("/tmp/fichero.xml"));
 8 
 9 
10 
11         } catch (FileNotFoundException ex) {
12             Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
13         } catch (SAXException ex) {
14             System.out.println("Fichero no pasa validación");
15             Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
16         } catch (IOException ex) {
17             Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
18         } catch (ParserConfigurationException ex) {
19             Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
20         }
21         
22         
23     }
  • Línea 7: El método parse está sobrecargado y podemos enviar un InputStream.
  • Las excepciones son las conocidas y dos nuevas. La principal es SAXException, que se lanzará en caso de que el fichero esté mal formado (no cumpla con las reglas de XML vistas en el punto inicial).




Accediendo un árbol DOM

  • Como comentamos anteriormente, cada par de etiquetas del archivo XML conforman un Element.


Obteniendo el elemento raíz

  • Para obtener el elemento raíz (nodo raíz) del documento (recordar que obligatoriamente debe existir para cumplir con el estándar XML) llamaremos al método getDocumentElement.
1             DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
2             Document doc = documentBuilder.parse(new File("/home/clase/Documentos/documento.xml"));
3             
4             Element raiz = doc.getDocumentElement();


  • Podemos saber el nombre de la etiqueta asociado a un elemento con el método getTagName() que devuelve un String.


Accediendo a los atributos de un Element

  • Una vez en dicho elemento podemos recuperar sus atributos (si tiene) de dos formas:
  • getAttribute(java.lang.String): Se le envía como parámetro el nombre del atributo y devuelve su valor siempre en String. En caso de que no exista el atributo, devuelve la cadena vacía.
  • getAttributeNode(java.lang.String): Se le envía como parámetro el nombre del atributo y devuelve un objeto de la clase Attr la cual dispone de métodos para obtener el nombre del atributo, obtener su valor, modificarlo,...Devuelve null en caso de que el atributo no exista.



Veamos un ejemplo (no se comprueba que los atributos existan):
 1             Element raiz = doc.getDocumentElement();
 2             
 3             
 4             System.out.println("Ejemplo de acceso a los atributos de un Element utilizando el método getAttribute");
 5             int numPedidos = Integer.parseInt(raiz.getAttribute("num_pedidos"));
 6             System.out.printf("Número de pedidos:%d%n",numPedidos);
 7             System.out.println("Fecha del pedido:" + raiz.getAttribute("fecha_pedido"));
 8             
 9             // Podemos pasar la fecha a Date por si queremos hacer operaciones sobre ella
10             DateFormat format = new SimpleDateFormat("dd-MM-yyyy",new Locale("es_ES"));
11             Date date = format.parse(raiz.getAttribute("fecha_pedido"));
12             System.out.printf("Fecha del pedido:%s%n",date);
13             
14             System.out.println("\nEjemplo de acceso a los atributos de un Element utilizando el método getAttributeNode");
15             Attr atribNumPedidos = raiz.getAttributeNode("num_pedidos");
16             System.out.printf("El nombre del atributo es %s y su valor es %s%n",atribNumPedidos.getName(),atribNumPedidos.getValue());
17             
18             Attr atribFechaPedido = raiz.getAttributeNode("fecha_pedido");
19             System.out.printf("El nombre del atributo es %s y su valor es %s%n",atribFechaPedido.getName(),atribNumPedidos.getValue());


Accediendo a los nodos dentro del árbol DOM

  • Podemos 'navegar' por el árbol DOM utilizando los métodos que se encuentran en la interface Node y que implementa la clase Element.
Entre ellos tenemos:
Todos estos métodos devuelve un objeto de la clase Node o un objeto de la clase NodeList (que viene a ser como un conjunto de Nodes, lo veremos después).
Un objeto de la clase Node puede representar entre otros:
Podemos averiguar a qué tipo pertenece llamando al método getNodeType() de la clase Node.
IMPORTANTE: En XML los saltos de línea del documento se transforman en espacios en blanco que también constituyen 'nodos' dentro del árbol (de tipo TEXT_NODE). Tendrás que tenerlos en cuenta para la navegación.


Veamos un ejemplo:
 1             Element raiz = doc.getDocumentElement();
 2             Node nodoResponsable = raiz.getFirstChild().getNextSibling();  // El primer hijo del raíz es el espacio en blanco del salto de línea
 3             if (nodoResponsable.getNodeType()==Node.ELEMENT_NODE){
 4                 System.out.println("Es un elemento del archivo XML");
 5                 System.out.println("Nombre de la etiqueta:" + nodoResponsable.getNodeName());
 6                 
 7                 Node textoResponsable = nodoResponsable.getFirstChild();
 8                 System.out.println("Texto de la etiqueta:" + textoResponsable.getNodeValue());
 9 
10                 System.out.println("Texto de la etiqueta:" + nodoResponsable.getTextContent());  // Otra forma de obtener el texto asociado a una etiqueta
11 
12             }


  • Importante: Como ya comentamos anteriormente debemos de tener en cuenta que si en el archivo hay 'enters', al pasarlo a un formato DOM, se van a transformar en espacios en blanco que van a conformar nodos de tipo texto en el árbol DOM.
Así, el archivo de muestra se transformaría en el siguiente árbol (cada rectángulo es un nodo del árbol) desde la etiqueta pedido:
Prog XML1D.jpg


  • Esto es debido a que al no definir un DTD, Java va a tratar los espacios en blanco/enters/tabuladores como información que debe preservar y por tanto creará un nodo asociado.
Más información en este enlace.




Ejercicio propuesto: Navega manualmente hasta <productos> y obtén el valor del atributo número de productos.
Después navega hasta el primer producto y obtén su código y cantidad.


Se le debe pasar el nombre de la 'etiqueta' a buscar y devolverá el conjunto de nodos del árbol que tenga esa etiqueta, en forma de objeto de la clase Nodelist.
Después tendremos que recorrer ese conjunto de nodos con un bucle desde 0 hasta el número de elementos (método getLength()) y obteniendo cada uno de nodos con el método item(int) de la clase NodeList.
Veamos un ejemplo:


1             NodeList nodosPedido = raiz.getElementsByTagName("pedido");
2             System.out.printf("Número de pedidos:%d",nodosPedido.getLength());
3             
4             for (int c=0;c<nodosPedido.getLength();c++){  // En este caso sólo devolverá uno ya que sólo hay un pedido
5                 Node nodoPedido = nodosPedido.item(c);
6                 
7             }
Por lo tanto, la forma más normal de recorrer un árbol es el de buscar por etiquetas y después navegar sobre ellas. Recordar que sobre cualquier nodo voy a poder obtener todos sus hijos o puedo buscar por un subnodo dentro del que te encuentres.
Un ejemplo de navegación del fichero de muestra podría ser:
  • Buscar por <id>. Tendremos un NodeList formadno por un nodo, id con texto 1. Si hubiera más nos devolvería en el NodeList todos los nodos id´s.
  • Por cada nodo id obtenido:
  • Obtener el texto del id(guardamos dicha información).
  • Ahora podemos ir al nodo productos de dos formas:
  • Ir al nodo siguiente al nodo id (dos veces, uno es el espacio en blanco y otro es el nodo productos)
  • Ir al nodo padre del nodo id y buscar por el nodo productos.
  • Una vez en el nodo productos obtemos sus atributos y los guardamos.
  • Estando en el nodo productos buscamos por los nodos producto. Devolverá dos nodos.
  • Por cada nodo producto, buscamos el nodo codigo y obtenemos su contenido y el nodo cantidad y obtenemos su contenido, que guardaríamos.


Ejercicio propuesto: Busca los nodos del árbol DOM que representen a un producto. Esto te devolverá un conjunto de nodos, cada uno de los cuales representa un producto. Busca los nodos codigo y cantidad y muestra sus valores.
Muestra el id del pedido del producto encontrado.
Recuerda que estando en un nodo puedes obtener el texto asociado llamando al método getTextContent(), sin necesidad de navegar hasta el nodo texto.


  • En los dos casos (navegar y buscar) acabaremos teniendo un objeto de la clase Node.
A partir de ella podemos:
  • Seguir navegando con los métodos que ya vimos.
  • Obtener los atributos.
  • Obtener los nodos hijos, anteriores y posteriores.
  • Operaciones sobre los nodos como añadir, eliminar o modificar.
Además, como ya comentamos, podemos hacer uso del método getType() para determinar el tipo de nodo y así hacer una conversión en función del tipo:
Veamos un ejemplo:
 1             NodeList nodosCodigo = raiz.getElementsByTagName("codigo");
 2             System.out.printf("Número de codigos:%d%n",nodosCodigo.getLength());
 3             
 4             for (int c=0;c<nodosCodigo.getLength();c++){
 5                 Node nodoCodigo = nodosCodigo.item(c);
 6                 if (nodoCodigo.getNodeType()==Node.ELEMENT_NODE){   // Esto ya lo sabemos porque lo estamos buscando.
 7                     Element codigo = (Element)nodoCodigo;
 8                     System.out.println("Nombre de la etiqueta:" + codigo.getTagName());
 9                     Node nodoTextoCodigo = codigo.getFirstChild();
10                     if (nodoTextoCodigo.getNodeType()==Node.TEXT_NODE){ // Ya lo sabemos
11                         Text textoCodigo = (Text)nodoTextoCodigo;
12                         System.out.println("Texto del código:" + textoCodigo.getWholeText());
13                     }
14                 }
15                 
16             }



Ejercicio propuesto: Añade un atributo a la etiqueta <producto> que indique si el producto es original o clónico.
Busca todos los productos o haciendo uso del método getChildNodes(), recorre todos los nodos. Cuando pases por el nodo producto (recuerda que es un 'Element'), muestra el id del pedido al que pertenece y el valor del atributo añadido.

Ejercicios propuestos

  • Dado el siguiente archivo XML:
<?xml version="1.0"?>
<company>
  <staff1>
    <name>john</name>
    <phone>465456433</phone>
    <email>gmail1</email>
    <area>area1</area>
    <city>city1</city>
  </staff1>
  <staff2>
    <name>mary</name>
    <phone>4655556433</phone>
    <email>gmail2</email>
    <area>area2</area>
    <city>city2</city>
  </staff2>
  <staff3>
    <name>furvi</name>
    <phone>4655433</phone>
    <email>gmail3</email>
    <area>area3</area>
    <city>city3</city>
  </staff3>
</company>
Crea las expresiones regulares necesarias para verificar que dicho archivo sólo contiene etiquetas: <staffXX>texto</staff> siendo XX un número, <name>texto</name>, <phone>9 números como máximo</phone>, <email>dir. correo válida</email>,<area>texto</area>,<city>texto, 30 caracteres como máximo</city>, <company> y </company>.
Lee el archivo de disco (recuerda no verificar la primera línea) y comprueba que pasa el filtro de la/s expresiones regulares creadas. Las líneas que no lo pasen saldrán por pantalla.
Paso dicho archivo a un árbol DOM y procésalo para crear una lista de objetos de una clase Staff creada por ti previamente.
Ordena dicha lista por nombre y ciudad.
Muestra los datos ordenados de las dos formas.


Parte de la solución la podéis encontrar en este enlace.

Modificando el contenido de un árbol DOM

  • Vamos a ver las operaciones básicas para modificar el contenido de un árbol DOM.
  • Existen otro tipo de operaciones que no vamos a ver, como la posibilidad de asociar a un nodo de un árbol un objeto a través de un valor clave asociado al nodo, mediante el método setUserData.
  • Normalmente vamos a querer modificar o bien el texto de asociado a una etiqueta o bien el valor de un atributo.


  • Modificar el valor del texto asociado a una etiqueta.
Tenemos de referencia a un objeto de la clase Node que representa esa etiqueta:
La diferencia entre los dos ya las vimos cuando vimos el punto de 'acceder'. Debemos de recordar que el texto de una etiqueta es también un nodo en el árbol.
Veamos un ejemplo de uso de estos dos métodos aplicado al contenido de la etiqueta 'responsable':
1             Node nodoResponsable = raiz.getElementsByTagName("responsable").item(0);
2 
3             nodoResponsable.setTextContent("Otro Angel");
4             System.out.println(nodoResponsable.getTextContent());
5             
6             nodoResponsable.getFirstChild().setNodeValue("Otro Angel 2");
7             String textoResponsable = nodoResponsable.getFirstChild().getNodeValue();
8             System.out.println(textoResponsable);
Línea 3: En este caso partimos de que nodoResponsable representa la etiqueta 'element' del árbol. Si aplicamos aquí el método getNodeValue() no nos devolverá el nombre del responsable ya que el nombre se encuentra en otro nodo (mirar el gráfico de la jerarquía en el punto anterior). Por eso hacemos uso del método getTextContent() y setTextContent() para cambiar su contenido.
Línea 5: En este caso nodoResponsable.getFirstChild() es el nodo donde se encuentra el texto asociado a la etiqueta. Ahora sí podemos hacer uso de los métodos getNodeValue() y setNodoValue().
  • Notas:
  • Recordar que Element es una interface que deriva de Node, por lo que un objeto de dicha clase también va a poder llamar a los métodos anteriores.
  • El método setTextContent elimina todos los nodos que tuviera por debajo del actual, sustituyéndolos por un nodo texto.


  • Modificar el valor de un atributo asociado a una etiqueta.
Tenemos de referencia a un objeto de la clase Node que representa esa etiqueta:
Necesitamos convertir el objeto de la clase Node a un objeto de la clase Element para utilizar el:
Para convertirlo sólo es necesario hacer un cast como ya vimos de la forma: ((Element)nodo).setAttribe()
En el caso de trabajar sobre el elemento raíz, recordar que el método getDocumentElement() ya devuelve un objeto de la clase Element y por tanto no habría que hacer conversión.


Veamos un ejemplo de uso aplicado al contenido de la etiqueta 'pedidos' y su atributo 'fecha_pedido':
1             Element raiz = doc.getDocumentElement();
2 
3             raiz.setAttribute("fecha_pedido", "01/01/2000");
4             System.out.println(raiz.getAttribute("fecha_pedido"));
Recordar que ya vimos anteriormente que disponemos del método hasAttribute(java.lang.String) para comprobar si existe antes de modificarlo.



Añadiendo nuevo contenido a un árbol DOM

  • Igual que en el caso de la modificación nos vamos a centrar en las operaciones para añadir nuevas etiquetas o nuevos atributos asociados a una etiqueta.
  • Añadir/Reemplazar/Eliminar nodos (etiquetas). (recordar que en el árbol DOM una etiqueta es un nodo, por lo tanto en este punto estamos modificando nodos del árbol).
Teniendo como referencia a un objeto de la clase Node que representa a una etiqueta, a partir de ella en el árbol, podemos llamar a::


Importante: Recordar que Node es una interface y por tanto no podemos crear un objeto directamente.
Para utilizar los métodos anteriores debemos de seguir estos pasos:
  • Tendremos un objeto de la clase Document: Document doc = documentBuilder.parse(new File("/home/clase/Documentos/documento.xml"));
Este objeto lo tendremos siempre para poder trabajar en DOM.
  • Crear un objeto de la clase Element, llamando al método createElement(java.lang.String) que es un método de clase Document (usaremos el objeto 'doc')
  • Crear un nuevo nodo de tipo texto, llamando al método createTextNode(java.lang.String) que es un método de clase Document (usaremos el objeto 'doc') y añadiéndoselo al objeto de la clase Element creado en el paso anterior.
  • Añadiendo el objeto de la clase Element al nodo que queramos haciendo uso de alguno de los métodos indicados anteriormente.


1             Element raiz = doc.getDocumentElement();
2 
3             Element nuevoElementFabrica =  doc.createElement("fabrica");  // Creamos la etiqueta <fabrica>
4             nuevoElementFabrica.appendChild(doc.createTextNode("Fabrica de Marruecos"));   // Creamos el texto 'Fabrica de Marruecos' y se la añadimos como un nodo hijo a la etiqueta <fabrica>
5             
6             raiz.appendChild(nuevoElementFabrica);  // Añadimos al nodo raíz un nuevo hijo, la etiqueta <fabrica> con el texto asociado.
Es decir, lo que estamos haciendo es crear los diferentes nodos a añadir (un nodo Element y un nodo Text) y se lo estamos añadiendo, en este caso, al nodo raíz.
Fijarse que appendChild() añade siempre al final.


  • Para eliminar nodos, normalmente tendremos que situarnos en el nodo padre y pasar 'una referencia' al nodo hijo que queremos eliminar.
Por ejemplo:
1             nodoResponsable.getParentNode().removeChild(nodoResponsable);
También podremos hacerlo son objetos de la clase Element:
1             NodeList nodosCantidad = raiz.getElementsByTagName("cantidad");
2             for (int c=0; c<nodosCantidad.getLength();c++){
3                 Element elementoCantidad = (Element)nodosCantidad.item(c);
4                 Element padre = (Element)elementoCantidad.getParentNode();
5                 padre.removeChild(elementoCantidad);
6             }
En el ejemplo se eliminarían todas las etiquetas 'cantidad' con sus valores (valdría no hacer el cast a Element)


  • Añadir/Eliminar atributos.
Debemos de hacer uso de los métodos que nos proporciona la clase Element:
Por ejemplo:
1             NodeList nodosProductos = raiz.getElementsByTagName("productos");
2             for (int c=0; c< nodosProductos.getLength();c++){
3                 Element elementoProducto = (Element)nodosProductos.item(0);
4                 elementoProducto.setAttribute("tipo_productos", "textil");
5             }
En este ejemplo estaríamos añadiendo un atributo nuevo (tipos_productos='textil') a todas las etiquetas 'productos'.



Pasando de un árbol DOM a un documento XML

  • Básicamente los pasos son:
  • Necesitamos importar todas estas clases:
1 import javax.xml.transform.Transformer;
2 import javax.xml.transform.TransformerFactory;
3 import javax.xml.transform.TransformerException;
4 import javax.xml.transform.TransformerConfigurationException;
5 import javax.xml.transform.dom.DOMSource; 
6 import javax.xml.transform.stream.StreamResult;
7 import java.io.*;
  • Después pondremos este código:
 1 String rutaArchivo="/tmp/archivo.xml";
 2 try {
 3     File ficheroSalida = new File(rutaArchivo);
 4 
 5     // Use a Transformer for output
 6     TransformerFactory tFactory = TransformerFactory.newInstance();  
 7     Transformer transformer = tFactory.newTransformer();    // Se podría realizar en un único paso: TransformerFactory.newInstance().newTransformer();
 8 
 9     transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");   // Indicamos la codificación
10     transformer.setOutputProperty(OutputKeys.INDENT, "yes");       // Indicamos si el contenido del fichero de salida está indentado
11             
12     DOMSource source = new DOMSource(doc);                         // doc es el objeto de la clase Document que hemos cargado previamente de disco y el cual queremos guardar.
13     StreamResult result = new StreamResult(ficheroSalida);         // Flujo de datos usado en XML
14     transformer.transform(source, result);
15 }
16     catch (TransformerException ex) {
17        Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex);
18 }


  • Si lo que se quiere es crear un nuevo documento XML desde cero, sin cargarlo previamente, podemos consultar cómo hacerlo en este enlace.
Básicamente es el siguiente código:
 1     DocumentBuilderFactory factory = null;
 2     DocumentBuilder builder = null;
 3     Document documento;
 4 
 5     try {
 6       factory = DocumentBuilderFactory.newInstance();
 7       builder = factory.newDocumentBuilder();
 8     } catch (ParserConfigurationException e) {
 9       e.printStackTrace();
10     }
11 
12     documento = builder.newDocument();  // Document creado.




Ejercicios propuestos

  • Crea a través de código un nuevo archivo XML que refleje la estructura (con datos de ejemplo) de un correo electrónico. Se quiere guardar en qué fecha fue enviado, quién lo envía, la dirección de correo de quién lo envía, la dirección de correo de a quién se envía, el mensaje, el número de archivos adjuntos y el nombre de cada uno de los archivos adjuntos (en caso de que lleve).




-- Ángel D. Fernández González -- (2017).