Con DOM, el archivo entero se carga en memoria como un árbol y puedes ir a cualquier nodo cuando quieras. Es lo cómodo mientras el archivo quepa; cuando no quepa, hay que pasar a SAX.
También te puede interesar
El XML de ejemplo
catalogo.xml<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<catalogo>
<libro id="1">
<titulo>El Quijote</titulo>
<autor>Cervantes & Saavedra</autor>
</libro>
</catalogo>Leerlo
import java.io.File;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
public class LeerXml {
public static void main(String[] args) throws Exception {
var fabrica = DocumentBuilderFactory.newInstance();
fabrica.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
fabrica.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
Document doc = fabrica.newDocumentBuilder().parse(new File("catalogo.xml"));
doc.getDocumentElement().normalize();
System.out.println("raíz: " + doc.getDocumentElement().getNodeName());
NodeList libros = doc.getElementsByTagName("libro");
System.out.println("libros: " + libros.getLength());
for (int i = 0; i < libros.getLength(); i++) {
Element e = (Element) libros.item(i);
System.out.println(" id : " + e.getAttribute("id"));
System.out.println(" titulo : " + texto(e, "titulo"));
System.out.println(" autor : " + texto(e, "autor"));
}
}
static String texto(Element e, String etiqueta) {
NodeList n = e.getElementsByTagName(etiqueta);
return n.getLength() == 0 ? null : n.item(0).getTextContent();
}
}salidaraíz: catalogo libros: 1 id : 1 titulo : El Quijote autor : Cervantes & Saavedra
El ampersand vuelve a aparecer sin escapar: el analizador deshace las entidades por ti. Y el método texto de abajo existe por una razón: getElementsByTagName puede devolver una lista vacía, y item(0) sobre ella da null y luego un NullPointerException en la línea siguiente. Es el fallo número uno al leer XML con DOM.
FEATURE_SECURE_PROCESSING y los accesos externos en blanco, el analizador se niega.Dos detalles de DOM que pillan a todo el mundo
getElementsByTagName busca en todo el subárbol, no solo en los hijos directos. Si hay un <titulo> anidado más abajo, también sale. Cuando eso importa, hay que recorrer getChildNodes() y filtrar.
Los espacios en blanco también son nodos. Un getChildNodes() sobre un XML sangrado devuelve nodos de texto con saltos de línea entre cada elemento. Por eso casi todo el mundo usa getElementsByTagName, y por eso se llama a normalize(), que junta los nodos de texto partidos.
Cuando la ruta es complicada, XPath
var xpath = javax.xml.xpath.XPathFactory.newInstance().newXPath();
String titulo = xpath.evaluate("/catalogo/libro[@id='1']/titulo", doc);Para sacar un dato concreto de un documento grande, una expresión XPath se lee mejor que cuatro bucles anidados. Viene en el JDK, sin dependencias.
| Si… | Usa |
|---|---|
| El archivo cabe en memoria | DOM, como en esta página |
| El archivo es enorme | SAX |
| Buscas un dato concreto | XPath |
| El XML viene de fuera | DOM o SAX, pero con la configuración segura |
| Quieres objetos Java directamente | JAXB o Jackson XML, ya con dependencias |
Más información en inglés: Read XML files in Java.
Todo el código se compiló y se ejecutó con Java 25 LTS en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.
Hola me sirvio bastante tu codigo, pero me he quedado con esta duda como consultar nodos de nodos o no se como ser mas explicito, me gustaria recorrer todo este en un while.
No necesitas de un while, porque cada elemento o lista de elementos se obtiene de forma explícita. En caso de tener más de un nodo del mismo tipo usas getElementsByTagName. Si desconoces el formato que tiene el XML quizá necesitas de un enfoque diferente para navegar tu XML, usar SAX por ejemplo, pero su implementación es más compleja. Saludos.