Manipulación de documentos XML en Python con xml.dom.minidom

XML (Lenguaje de Marcado Extensible) es un formato estándar diseñado para almacenar y transportar datos. Se define mediante una estructura de etiquetas que permiten organizar la información de manera jerárquica. La estructura básica incluye pares de etiquetas (por ejemplo, <nodo></nodo>), atributos dentro de las etiquetas (como <nodo id="101">) y datos anidados entre ellas.

Para la manipulación de estos archivos en Python, el ecosistema estándar ofrece varias librerías:

  • xml.etree.ElementTree: Es una opción ligera y eficiente, ideal para tareas simples. Funciona como una versión simplificada del modelo DOM, consumiendo menos memoria y ofreciendo una API intuitiva.
  • xml.dom.*: Implementa el modelo de Documento de Objetos (DOM), cargando todo el documento en memoria como un árbol de nodos. Es útil cuando se requiere acceso aleatorio a partes del archivo.
  • xml.sax.*: Utiliza un modelo basado en eventos. Es útil para archivos muy grandes, ya que no carga todo en memoria, sino que dispara eventos (como inicio de etiqueta o fin de etiqueta) a medida que lee el flujo de datos.

Escritura de documentos XML

Para generar arhcivos XML mediante programación, el módulo xml.dom.minidom facilita la creación de nodos, atributos y estructura jerárquica. A continuación, se presenta una implementación refactorizada para crear un archivo de configuración:

import xml.dom.minidom

def construir_xml_archivo(ruta_salida):
    # Instanciar el documento DOM
    documento = xml.dom.minidom.Document()
    
    # Crear el elemento raíz y definir sus atributos
    nodo_raiz = documento.createElement('SistemaConfig')
    nodo_raiz.setAttribute('version', '2.0')
    nodo_raiz.setAttribute('xmlns', 'http://ejemplo.com/esquema')
    documento.appendChild(nodo_raiz)
    
    # Crear un nodo hijo con atributos
    modulo_usuario = documento.createElement('Modulo')
    modulo_usuario.setAttribute('id', 'usr-001')
    nodo_raiz.appendChild(modulo_usuario)
    
    # Añadir contenido de texto al nodo hijo
    texto_descripcion = documento.createTextNode('Módulo de autenticación principal')
    modulo_usuario.appendChild(texto_descripcion)
    
    # Añadir un sub-elemento dentro del módulo
    etiqueta_meta = documento.createElement('MetaInfo')
    etiqueta_meta.setAttribute('estado', 'activo')
    modulo_usuario.appendChild(etiqueta_meta)
    
    # Persistir el documento en disco con formato indentado
    with open(ruta_salida, 'w', encoding='utf-8') as archivo:
        archivo.write(documento.toprettyxml(indent="  "))

if __name__ == '__main__':
    construir_xml_archivo('configuracion_generada.xml')

Este script crea una estructura jerárquica y la guarda en el disco. El uso de toprettyxml asegura que el archivo resultante tenga una sangría legible para humanos.

Lectura y parseo de documentos XML

La lectura de un archivo XML existente implica parsear el contenido y navegar por el árbol de nodos. El siguiente ejemplo muestra cómo extraer información específica, verificar atributos y distinguir entre nodos de texto y nodos de elementos:

import xml.dom.minidom

def procesar_xml_archivo(ruta_entrada):
    # Cargar y parsear el archivo XML
    arbol_dom = xml.dom.minidom.parse(ruta_entrada)
    elemento_raiz = arbol_dom.documentElement
    
    # Recuperar una lista de elementos por su nombre de etiqueta
    lista_modulos = elemento_raiz.getElementsByTagName('Modulo')
    
    for modulo in lista_modulos:
        # Verificar y obtener atributos
        if modulo.hasAttribute('id'):
            id_modulo = modulo.getAttribute('id')
            print(f"ID encontrado: {id_modulo}")
            
        # Iterar sobre los nodos hijos del elemento actual
        for hijo in modulo.childNodes:
            # Verificar si el nodo es texto (incluido espacios en blanco)
            if hijo.nodeType == hijo.TEXT_NODE:
                contenido = hijo.data.strip()
                if contenido:
                    print(f"\tContenido de texto: {contenido}")
            
            # Si es un nodo elemento, procesar sus atributos
            elif hijo.nodeType == hijo.ELEMENT_NODE:
                print(f"\tSub-elemento detectado: {hijo.tagName}")
                # Iterar sobre el diccionario de atributos
                for nombre_attr, valor_attr in hijo.attributes.items():
                    print(f"\t\tPropiedad [{nombre_attr}]: {valor_attr}")
        print("-" * 20)

if __name__ == '__main__':
    procesar_xml_archivo('configuracion_generada.xml')

Etiquetas: Python XML xml.dom.minidom parsing Serialización

Publicado el 9-29 03:13