Saltar al contenido

Apuntes DOM en Java: SELECT, INSERT, UPDATE y DELETE sobre XML

A partir de tu helper:

private static Document cargarDocumento(String ruta) throws Exception {
    File archivo = new File(ruta);
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = factory.newDocumentBuilder();
    Document doc = builder.parse(archivo);
    doc.getDocumentElement().normalize();
    return doc;
}

Ideas clave del DOM

  • Document es todo el árbol XML en memoria (mutable).
  • Element representa etiquetas; Attr atributos; Text el contenido.
  • Muchas operaciones empiezan con doc.getElementsByTagName("...") o navegando con getChildNodes().
  • Tras modificar el árbol, hay que guardarlo con Transformer.

SELECT (leer/recorrer)

Patrón básico por etiqueta

NodeList nodos = doc.getElementsByTagName("TAG_OBJETO"); // p.ej. "Libro"
for (int i = 0; i < nodos.getLength(); i++) {
    Node nodo = nodos.item(i);
    if (nodo.getNodeType() == Node.ELEMENT_NODE) {
        Element e = (Element) nodo;

        // Leer atributo
        String id = e.getAttribute("id"); // si existe

        // Leer subelemento (siempre comprobar nulls/length)
        Element tituloEl = (Element) e.getElementsByTagName("Titulo").item(0);
        String titulo = (tituloEl != null) ? tituloEl.getTextContent() : "";

        // ...procesar/mostrar
    }
}

Búsqueda por atributo “id”

Element buscarPorId(Document doc, String tag, String idBuscado) {
    NodeList nl = doc.getElementsByTagName(tag);
    for (int i = 0; i < nl.getLength(); i++) {
        Element e = (Element) nl.item(i);
        if (idBuscado.equals(e.getAttribute("id"))) return e;
    }
    return null;
}

Nota: si necesitas consultas más potentes, puedes usar XPath (opcional en apuntes), pero con DOM puro suele bastar.


INSERT (crear y añadir nodos)

Patrón básico (crear elemento con hijos y atributos)

void insertarObjeto(Document doc) {
    // 1) Crear el nuevo elemento
    Element nuevo = doc.createElement("TAG_OBJETO");       // p.ej. "Libro"
    nuevo.setAttribute("id", "123");                       // atributo opcional

    // 2) Crear y añadir subelementos
    Element titulo = doc.createElement("Titulo");
    titulo.setTextContent("Título de ejemplo");
    nuevo.appendChild(titulo);

    Element autor = doc.createElement("Autor");
    autor.setTextContent("Nombre Apellidos");
    nuevo.appendChild(autor);

    // 3) Insertar en el padre adecuado (p.ej. raíz o una colección)
    Element raiz = doc.getDocumentElement();               // p.ej. "Catalogo"
    raiz.appendChild(nuevo);

    // (Opcional) Insertar en posición concreta:
    // raiz.insertBefore(nuevo, raiz.getFirstChild());
}

Buenas prácticas al insertar

  • Decide el padre correcto (raíz o un contenedor tipo <Libros>).
  • Define siempre los atributos obligatorios (p.ej. id) antes de guardar.
  • Si el orden importa, usa insertBefore.

UPDATE (modificar contenido/atributos)

Cambiar texto de un subelemento

void actualizarTitulo(Document doc, String idLibro, String nuevoTitulo) {
    Element libro = buscarPorId(doc, "Libro", idLibro);
    if (libro == null) return;

    Element titulo = (Element) libro.getElementsByTagName("Titulo").item(0);
    if (titulo == null) {
        titulo = doc.createElement("Titulo");
        libro.appendChild(titulo);
    }
    titulo.setTextContent(nuevoTitulo);
}

Cambiar/añadir un atributo

void actualizarAtributo(Document doc, String idLibro, String nombreAttr, String valor) {
    Element libro = buscarPorId(doc, "Libro", idLibro);
    if (libro != null) {
        libro.setAttribute(nombreAttr, valor); // crea si no existe
    }
}

Reemplazar un nodo completo

void reemplazarNodo(Document doc, Element viejo, Element nuevo) {
    Node padre = viejo.getParentNode();
    padre.replaceChild(nuevo, viejo);
}

Consejos UPDATE

  • Comprueba null/longitudes antes de item(0).
  • Si el subelemento no existe, créalo para mantener el esquema consistente.

DELETE (eliminar nodos)

Borrar un elemento por id

void borrarPorId(Document doc, String idLibro) {
    Element libro = buscarPorId(doc, "Libro", idLibro);
    if (libro != null) {
        Node padre = libro.getParentNode();
        padre.removeChild(libro);
    }
}

Borrado seguro en bucles

Si vas a borrar varios elementos mientras iteras un NodeList, itera al revés:

NodeList nl = doc.getElementsByTagName("Libro");
for (int i = nl.getLength() - 1; i >= 0; i--) {
    Element e = (Element) nl.item(i);
    if (/* condición de borrado */) {
        e.getParentNode().removeChild(e);
    }
}

Guardar cambios a disco (obligatorio tras INSERT/UPDATE/DELETE)

static void guardarDocumento(Document doc, String ruta) throws Exception {
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer t = tf.newTransformer();
    t.setOutputProperty(OutputKeys.INDENT, "yes");
    t.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    // (Opcional) Mejorar sangría con implementaciones que soporten:
    // t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");

    DOMSource source = new DOMSource(doc);
    StreamResult result = new StreamResult(new File(ruta));
    t.transform(source, result);
}

Notas de guardado

  • Si no llamas a guardarDocumento, los cambios quedan solo en memoria.
  • Asegura codificación (UTF-8) si manejas tildes/ñ.

Utilidades y buenas prácticas

  • Factory configurado: cuando trabajes con namespaces o quieras ignorar espacios, puedes ajustar: DocumentBuilderFactory f = DocumentBuilderFactory.newInstance(); f.setNamespaceAware(true); // f.setIgnoringElementContentWhitespace(true); // requiere validación DTD
  • normalize() (ya lo haces) ayuda a juntar nodos de texto contiguos.
  • Comprobación de tipos: if (n.getNodeType() == Node.ELEMENT_NODE) antes de castear.
  • Validación: si tu XML tiene DTD/XSD, valida para detectar errores de esquema.
  • IDs únicos: si usas id como clave, mantén un generador/validador de unicidad.
  • Errores comunes:
    • NullPointerException por asumir que item(0) existe.
    • Guardar sin INDENT y luego “perder” legibilidad (no es error funcional, pero molesta).
    • Borrar en orden ascendente (puede saltarse nodos).

Esqueleto típico de menú (solo guía, no solución)

Document doc = cargarDocumento("Catalogo.xml");

switch(opcion) {
  case 1: // SELECT
    // listar/filtrar y mostrar campos
    break;
  case 2: // INSERT
    // construir elemento y append al padre
    // guardarDocumento(doc, "Catalogo.xml");
    break;
  case 3: // UPDATE
    // localizar por id/criterio, setTextContent/setAttribute
    // guardarDocumento(doc, "Catalogo.xml");
    break;
  case 4: // DELETE
    // localizar y removeChild
    // guardarDocumento(doc, "Catalogo.xml");
    break;
}

Con esto tienes los patrones de trabajo para SELECT/INSERT/UPDATE/DELETE usando DOM, sin resolver un ejercicio concreto. Solo adapta los TAG_..., nombres de campos y criterios a tu XML real.

Etiquetas:

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Información básica sobre protección de datos Ver más

  • Responsable: Tomas Gonzalez.
  • Finalidad:  Moderar los comentarios.
  • Legitimación:  Por consentimiento del interesado.
  • Destinatarios y encargados de tratamiento:  No se ceden o comunican datos a terceros para prestar este servicio.
  • Derechos: Acceder, rectificar y suprimir los datos.
  • Información Adicional: Puede consultar la información detallada en la Política de Privacidad.

¿Atascado con tu proyecto? Presupuesto GRATIS

X
error: Content is protected !!
Este sitio web utiliza cookies, si necesitas más información puedes visitar nuestra política de privacidad    Ver
Privacidad