Cómo leer y escribir archivos XML con Java
La popularidad de XML ha disminuido recientemente, pero es posible que lo encuentres ocasionalmente, por lo que es importante aprender a leer y escribir un archivo XML.
Los archivos XML pueden servir para una variedad de propósitos, incluido el almacenamiento de datos. Antes de que JSON se hiciera popular, XML era el formato preferido para representar, almacenar y transportar datos estructurados.
Aunque la popularidad de XML ha disminuido en los últimos años, es posible que lo encuentre ocasionalmente, por lo que es importante aprender a trabajar con él. Descubra cómo utilizar la API DOM para leer y escribir archivos XML con Java.
Requisitos para procesar XML en Java
Java Standard Edition (SE) incluye la API de Java para procesamiento XML (JAXP), que es un término general que cubre la mayoría de los aspectos del procesamiento XML. Éstas incluyen:
- DOM: El modelo de objetos de documento incluye clases para trabajar con objetos XML como elementos, nodos y atributos. La API DOM carga el documento XML completo en la memoria para su procesamiento, por lo que no es muy adecuada para archivos XML grandes.
- SAX: La API simple para XML es una API basada en eventos para leer XML. Activa eventos en respuesta al contenido XML que encuentra al analizar un archivo. El consumo de memoria de este método es bajo, pero trabajar con la API es más difícil que trabajar con el DOM.
- StAX: La API de streaming para XML es una incorporación reciente. Proporciona filtrado, procesamiento y modificación de flujos de XML de alto rendimiento. Si bien evita cargar todo el documento XML en la memoria, proporciona una arquitectura de tipo pull en lugar de una arquitectura basada en eventos, por lo que es más fácil de codificar que la API SAX.
Para procesar XML en Java, necesitará importar estos paquetes:
import javax.xml.parsers.*;
import javax.xml.transform.*;
import org.w3c.dom.*;
Preparar un archivo XML de muestra
Para comprender el código de muestra y los conceptos detrás de él, utilice este archivo XML de muestra de Microsoft. Aquí hay un extracto:
<?xml version="1.0"?>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
...snipped...
Leer el archivo XML con la API DOM
Veamos los pasos básicos necesarios para leer un archivo XML utilizando la API DOM. Comience creando una instancia de DocumentBuilder que usará para analizar el documento XML:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Ahora puede cargar todo el documento en la memoria, comenzando desde el elemento raíz XML. En nuestro ejemplo, es el elemento catalog.
// XML file to read
File file = "<path_to_file>";
Document document = builder.parse(file);
Element catalog = document.getDocumentElement();
Y eso es; Ahora tiene acceso a todo el documento XML a partir de su elemento raíz, catálogo.
Extracción de información utilizando la API DOM
Ahora que tiene el elemento raíz XML, puede utilizar la API DOM para extraer información interesante. Por ejemplo, obtenga todos los libro secundarios del elemento raíz y recorralos. Tenga en cuenta que getChildNodes() devuelve todos los elementos secundarios, incluido texto, comentarios, etc. Para su propósito, solo necesita los elementos secundarios, por lo que puede omitir los demás:
NodeList books = catalog.getChildNodes();
for (int i = 0, ii = 0, n = books.getLength() ; i < n ; i++) {
Node child = books.item(i);
if ( child.getNodeType() != Node.ELEMENT_NODE )
continue;
Element book = (Element)child;
// work with the book Element here
}
¿Cómo se encuentra un elemento secundario específico, dado el padre? Cree un método estático que devuelva el primer elemento coincidente, si se encuentra, o sea nulo. El procedimiento implica obtener la lista de nodos secundarios y recorrerlos seleccionando nodos de elementos con el nombre especificado.
static private Node findFirstNamedElement(Node parent,String tagName)
{
NodeList children = parent.getChildNodes();
for (int i = 0, in = children.getLength() ; i < in ; i++) {
Node child = children.item(i);
if (child.getNodeType() != Node.ELEMENT_NODE)
continue;
if (child.getNodeName().equals(tagName))
return child;
}
return null;
}
Tenga en cuenta que la API DOM trata el contenido de texto dentro de un elemento como un nodo separado de tipo TEXT_NODE. El contenido de texto puede consistir en múltiples nodos de texto adyacentes, por lo que necesitarás un procesamiento especial para recuperar el texto de un elemento:
static private String getCharacterData(Node parent)
{
StringBuilder text = new StringBuilder();
if ( parent == null )
return text.toString();
NodeList children = parent.getChildNodes();
for (int k = 0, kn = children.getLength() ; k < kn ; k++) {
Node child = children.item(k);
if (child.getNodeType() != Node.TEXT_NODE)
break;
text.append(child.getNodeValue());
}
return text.toString();
}
Armado con estas funciones convenientes, eche un vistazo a este código para enumerar información del XML de muestra. Muestra información detallada de cada libro disponible en un catálogo:
NodeList books = catalog.getChildNodes();
for (int i = 0, ii = 0, n = books.getLength() ; i < n ; i++) {
Node child = books.item(i);
if (child.getNodeType() != Node.ELEMENT_NODE)
continue;
Element book = (Element)child;
ii++;
String id = book.getAttribute("id");
String author = getCharacterData(findFirstNamedElement(child, "author"));
String title = getCharacterData(findFirstNamedElement(child, "title"));
String genre = getCharacterData(findFirstNamedElement(child, "genre"));
String price = getCharacterData(findFirstNamedElement(child, "price"));
String pubdate = getCharacterData(findFirstNamedElement(child, "pubdate"));
String descr = getCharacterData(findFirstNamedElement(child, "description"));
System.out.printf("%3d. book id = %s\n" +
" author: %s\n" +
" title: %s\n" +
" genre: %s\n" +
" price: %s\n" +
" pubdate: %s\n" +
" descr: %s\n",
ii, id, author, title, genre, price, pubdate, descr);
}
Aquí hay una explicación paso a paso del código:
- El código recorre en iteración los nodos secundarios de catalog, el elemento raíz.
- Para cada nodo secundario, que representa un libro, verifica si el tipo de nodo es un ELEMENT_NODE. Si no, continúa con la siguiente iteración.
- Si el nodo secundario es un ELEMENT_NODE, (Element)child lo convierte en un objeto Element.
- Luego, el código extrae varios atributos y datos de caracteres del elemento del libro, incluidos "id", "autor", "título", "género", "precio", "fecha de publicación" y "descripción". Imprime estos datos utilizando el método System.out.printf.
Así es como se ve el resultado:
Escribir salida XML utilizando la API de transformación
Java proporciona la API de transformación XML para transformar datos XML. Usamos esta API con la identidad transform para generar resultados. Como ejemplo, agreguemos un nuevo elemento libro al catálogo de muestra presentado anteriormente.
Puede obtener los detalles de un libro (autor, título, etc.) de una fuente externa, como un archivo de propiedades o una base de datos. Puede utilizar el siguiente archivo de propiedades como ejemplo:
id=bk113
author=Jane Austen
title=Pride and Prejudice
genre=Romance
price=6.99
publish_date=2010-04-01
description="It is a truth universally acknowledged, that a single man in possession of a good fortune must be in want of a wife." So begins Pride and Prejudice, Jane Austen's witty comedy of manners-one of the most popular novels of all time-that features splendidly civilized sparring between the proud Mr. Darcy and the prejudiced Elizabeth Bennet as they play out their spirited courtship in a series of eighteenth-century drawing-room intrigues.
El primer paso es analizar el archivo XML existente utilizando el método presentado anteriormente:
File file = ...; // XML file to read
Document document = builder.parse(file);
Element catalog = document.getDocumentElement();
Ahora carga los datos del archivo de propiedades usando la clase Properties proporcionada en Java. El código es bastante simple:
String propsFile = "<path_to_file>";
Properties props = new Properties();
try (FileReader in = new FileReader(propsFile)) {
props.load(in);
}
Una vez que haya cargado las propiedades, puede recuperar los valores que desea agregar del archivo de propiedades:
String id = props.getProperty("id");
String author = props.getProperty("author");
String title = props.getProperty("title");
String genre = props.getProperty("genre");
String price = props.getProperty("price");
String publish_date = props.getProperty("publish_date");
String descr = props.getProperty("description");
Ahora, crea un elemento libro vacío.
Element book = document.createElement("book");
book.setAttribute("id", id);
Agregar los elementos secundarios al libro es trivial. Para mayor comodidad, puede recopilar los nombres de los elementos necesarios en una Lista y agregar los valores en un bucle.
List<String> elnames =Arrays.asList("author", "title", "genre", "price",
"publish_date", "description");
for (String elname : elnames) {
Element el = document.createElement(elname);
Text text = document.createTextNode(props.getProperty(elname));
el.appendChild(text);
book.appendChild(el);
}
catalog.appendChild(book);
El elemento catalog ahora tiene agregado el nuevo elemento libro. Todo lo que queda ahora es escribir el XML actualizado.
Para escribir el XML, necesita una instancia de Transformer que puede crear de esta manera:
TransformerFactory tfact = TransformerFactory.newInstance();
Transformer tform = tfact.newTransformer();
tform.setOutputProperty(OutputKeys.INDENT, "yes");
tform.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");
Puede utilizar setOutputProperty() para solicitar la sangría de la salida.
El último paso es aplicar la transformación. El resultado aparece en el flujo de salida, System.out.
tform.transform(new DOMSource(document), new StreamResult(System.out));
Para escribir la salida directamente en un archivo, utilice lo siguiente:
tform.transform(new DOMSource(document), new StreamResult(new File("output.xml")));
Esos son todos los pasos que necesita para leer y escribir archivos XML en Java.
Ahora ya sabe cómo leer y escribir archivos XML con Java
Analizar y manipular XML con Java es una habilidad valiosa que utilizará a menudo en programas del mundo real. Las API DOM y Transform son particularmente útiles.
Comprender el DOM, en particular, es vital si planea escribir código del lado del cliente para aplicaciones o sitios web. La interfaz del DOM es universal, por lo que puedes trabajar con ella usando código similar en lenguajes tan diversos como Java y JavaScript.