Crear archivo XML desde Java

Estándar
XML a la vieja usanza

XML a la vieja usanza

Con la popularidad de servicios SOAP y el almacenamiento de archivos en XML, es buena idea saber el como crearlos, mas aun con la impresionante cantidad de librerías con esa capacidad, cada una con sus pros, contras y enfoques, sin embargo no hay que olvidar que el propio Java contiene las librerías precisamente para crear documentos XML, llamadas Java API for XML Processing, JAXP que es bastante sencilla de usar, por lo que vale la pena darle un vistazo.

Base teorica de JAXP.

La forma en que opera la libreria JAXP para crear un documento XML es la siguiente:

  1. Creamos una nueva instancia DocumentBuilderFactory
  2. Creamos un objeto DocumentBuilder
  3. Creamos el objeto Document, este representa nuestro XML
  4. Creamos objetos Element, los que representan las diferentes secciones del XML
  5. Establecemos el contenido de dicho objecto Element
  6. indicamos de que elemento desciende el que acabamos de crear

Los pasos 4 y 6 se repetirían para cada elemento que deseamos agregar al XML, el ultimo paso puede sonar algo confuso, pero si conoce la estructura del XML sabra que las etiquetas usualmente van anidadas en forma jerárquica el paso 6 es cuando indicamos de que elemento desciende el elemento que acabamos de crear.

Conversión de Document a texto.

Aunque seria tentador pensar que el objeto Document contiene un sencillo método .toString que nos regresaria el contenido del archivo en texto plano, esto lamentablemente no es asi, la labor de convertir nuestro documento XML a un archivo o cadena de texto recae en el la clase javax.xml.trasnform.Transformer y su metodo transform.

El procedimiento para pasar de un Documento a un archivo que contenga el XML es el siguiente:

  1. Creamos un objeto Transformer, el cual efectuará la conversión con su método transform
  2. Creamos un objeto File el cual representa el archivo donde deseamos almacenar el documento
  3. Creamos un objeto DOMSource pasándole como argumento el objeto Document, este objeto representa la fuente que usara la clase Transformer para efectuar la transformación.
  4. Creamos un objeto StreamResult pasándole como argumento el objeto File que creamos previamente, este objeto es donde se almacenara el resultado del método Transformer.transform , al pasarle como argumento el File indicamos que deseamos almacenar el resultado en ese archivo este objeto se encargara de todo lo necesario para eso
  5. Llamamos al método transform del objecto Transformer que creamos previamente, pasándole como argumento el DOMSource que creamos previamente y el StreamResult, esto tomara los datos del DOMSource y pasara al formato que indique el StreamResult

Ya es un tema recurrente mencionar que esto suena demasiado a sobre ingeniera pero de nuevo la idea es dar la mayor flexibilidad posible y mantener una muy clara división de los pasos,

Descripción de las clases.

org.w3c.dom.Document : Esta clase representa el documento y el nodo <XML> del documento, el nodo principal de la jerarquia.

org.w3c.dom.Element : Cada objeto de esta clase representa un nodo del documento XML, y el contenido de este nodo, a cada elemento se le debe establecer su elemento “padre”, el cual puede ser otro objeto Element o el propio documento XML.

javax.xml.transform.Transformer : Esta clase transforma un documento XML en la salida que deseemos, ya que esta es una clase abstracta no podemos instanciarla con un constructor, por lo que necesita llamar al método newInstance de un objecto TransformerFactory. El método interesante aquí es el transform, el cual efectúa la transformación, este método le pide una fuente y una salida donde se almacenara el resultado de la transformación.

java.io.StringWriter : Convierte un flujo de salida en una cadena de texto, se usa para convertir salidas en cadenas de texto

javax.xml.transform.dom.DOMSource : Este objeto actua para contener el DOM de un documento, se usa como fuente para el método transform

javax.xml.transform.stream.StreamResult : Contiene el resultado de la transformación del documento DOM ,se le pasa como argumento donde se almacenara la salida ya sea un StringWriter para almacenar en cadena de texto o un File para almacenar en ese archivo.

Almacenando en un archivo.

Una vez que que tenemos los datos contenidos en nuestro objecto Document es necesitaremos almacenarlo, puede ser en un archivo completo o como una cadena de texto en una base de datos, ambas opciones son posibles con las clases Transformer, StringWriter y StreamResult los cuales nos permitirían convertir el objecto Document a la salida que deseemos

Ejemplo.

Todo esto suena complicado, por lo que se presentara un ejemplo de como hacerlo a continuación:

package xmlmaker;

import java.io.File;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

// Clases para la creacion y manejo de XML
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class XMLMaker {

    // Objecto que representa al documento XML
    Document documento;

    /**
     * Creamos el documento XML
     *
     * @throws ParserConfigurationException
     */
    public XMLMaker() throws ParserConfigurationException {
        // Creamos los objectos de creacion de Documentos XML
        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder constructor = docFactory.newDocumentBuilder();

        // Creamos el documento XML
        documento = constructor.newDocument();
    }

    /**
     * Regresa el documento “plano” sin saltos de linea
     *
     * @return Documento XML plano
     * @throws TransformerConfigurationException
     * @throws TransformerException
     */
    public String convertirString() throws TransformerConfigurationException, TransformerException {
        // Creamos el objecto transformador
        TransformerFactory tf = TransformerFactory.newInstance();        
        Transformer transformer = tf.newTransformer();
        // Creamos el escritor a cadena de texto
        StringWriter writer = new StringWriter();
        // Fuente de datos, en este caso el documento XML
        DOMSource source = new DOMSource(documento);
        // Resultado, el cual se almacenara en el objecto writer
        StreamResult result = new StreamResult(writer);
        // Efectuamos la transformacion a lo que indica el objecto resultado, writer apuntara a el resultado
        transformer.transform(source, result);
        // Convertimos el buffer de writer en cadena de texto
        String output = writer.getBuffer().toString();

        return output;
    }

    /**
     * Envia el documento XML a un archivo
     * @throws TransformerConfigurationException
     * @throws TransformerException
     */
    public void escribirArchivo() throws TransformerConfigurationException, TransformerException {
        // Creamos el objecto transformador
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        
        // Archivo donde almacenaremos el XML
        File archivo = new File(“entrada.xml”);
        
        // Fuente de datos, en este caso el documento XML
        DOMSource source = new DOMSource(documento);
        // Resultado, el cual almacena en el archivo indicado
        StreamResult result = new StreamResult(archivo);
        // Transformamos de ña fuente DOM a el resultado, lo que almacena todo en el archivo
        transformer.transform(source, result);
    }

    /**
     * Creamos un documento con un elemento principal y varios subElementos
     */
    public void crearDocumento() {
        // Creamos el elemento principal
        Element entrada = documento.createElement(“ENTRADA”);
        // Hacemos el elemento entrada descender directo del nodo XML principal
        documento.appendChild(entrada);

        // Creamos el Elemento de titulo
        Element titulo = documento.createElement(“TITULO”);
        // Establecemos el contenido del titulo
        titulo.setTextContent(“Creacion de XML”);
        // Indicamos que el elemento titulo desciende de entrada
        entrada.appendChild(titulo);

        //Creamos mas elementos
        Element autor = documento.createElement(“AUTOR”);
        autor.setTextContent(“hashRaygoza”);
        entrada.appendChild(autor);

        //Elemento fecha
        Element fecha = documento.createElement(“FECHA”);
        SimpleDateFormat formato = new SimpleDateFormat(“yyyy-MM-dd”);
        Calendar calendario = Calendar.getInstance();
        Date date = new Date(calendario.getTimeInMillis());

        fecha.setTextContent(formato.format(date));
        entrada.appendChild(fecha);
    }

    /**
     * Usamos todas las funciones
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            XMLMaker creador = new XMLMaker();

            creador.crearDocumento();
            creador.escribirArchivo();
            System.out.println( creador.convertirString() );

        } catch (ParserConfigurationException ex) {
            Logger.getLogger(XMLMaker.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TransformerException ex) {
            Logger.getLogger(XMLMaker.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Basta con que cree un proyecto en NetBeans con este código y podra calar, el método crearDocumento es el principal donde puede agregar o quitar Elementos, experimente con esa parte para lograr la estructura deseada.