Leer XML con Python: guía novatos con ElementTree y lxml

1. Lo que debes saber antes de leer XML con Python

¿En qué situaciones se maneja XML con Python?

Python es un lenguaje de programación de propósito general usado en muchos ámbitos, y entre ellos la “lectura de archivos XML” es una de las técnicas frecuentemente utilizadas en el procesamiento de datos. En particular, en los siguientes casos se necesita leer XML con Python.

  • Quiero analizar datos XML obtenidos de una API web
  • Quiero procesar archivos XML exportados desde otros sistemas
  • Quiero leer XML que se utiliza como archivo de configuración (config)

XML permite expresar claramente la jerarquía y el significado de los datos mediante una estructura de etiquetas, por lo que se utiliza en diversas industrias. Con Python, es posible leer, transformar y analizar fácilmente estos datos XML.

¿Qué es XML? Repaso rápido

XML (Extensible Markup Language) es un lenguaje de marcado que permite definir de forma flexible la estructura de los datos. Tiene una estructura similar a HTML, pero su uso es diferente. Mientras que HTML se utiliza para la presentación (visual), XML es un formato para describir la estructura y el significado de los datos.

Por ejemplo, el siguiente formato es un XML típico:

<book>
  <title>Introducción a Python</title>
  <author>Tarō Yamada</author>
  <price>2800</price>
</book>

Para leer y utilizar datos en este formato con Python, es necesario usar una biblioteca especializada.

Bibliotecas para leer XML en Python

Python ofrece varias opciones, tanto en la biblioteca estándar como en bibliotecas externas, para leer XML. Las más representativas son las siguientes.

  • xml.etree.ElementTree (biblioteca estándar)
  • xml.dom.minidom (biblioteca estándar)
  • lxml (biblioteca externa, compatible con XPath y validación)

En este artículo explicaremos de manera clara, con ejemplos de código, cómo leer archivos XML con Python usando estas bibliotecas. Incluso los principiantes podrán seguirlo, ya que introduciremos los conceptos desde lo básico de forma cuidadosa, así que no se preocupe.

2. Conceptos básicos para leer XML con Python

Lectura de archivos XML con ElementTree

Primero, veamos cómo leer usando ElementTree con un archivo XML real.

XML de ejemplo (sample.xml):

<books>
  <book>
    <title>Introducción a Python</title>
    <author>Taro Yamada</author>
    <price>2800</price>
  </book>
  <book>
    <title>El futuro de la IA</title>
    <author>Ichiro Suzuki</author>
    <price>3500</price>
  </book>
</books>

Código Python:

import xml.etree.ElementTree as ET

# Lectura del archivo XML
tree = ET.parse('sample.xml')
root = tree.getroot()

# Verificar la etiqueta del elemento raíz
print(f"Elemento raíz: {root.tag}")

# Procesar cada elemento book en bucle
for book in root.findall('book'):
    title = book.find('title').text
    author = book.find('author').text
    price = int(book.find('price').text)

    print(f"Título: {title}, Autor: {author}, Precio: {price}¥")

Resultado de la ejecución:

Elemento raíz: books
Título: Introducción a Python, Autor: Taro Yamada, Precio: 2800 yen
Título: Futuro de la IA, Autor: Ichiro Suzuki, Precio: 3500 yen

De esta manera, ElementTree.parse() lee el archivo XML, getroot() obtiene el elemento raíz, y find() o findall() extraen los elementos necesarios; este es el flujo básico.

Cómo leer XML desde una cadena

A veces el XML se proporciona como una cadena en lugar de un archivo. En ese caso, se analiza usando ET.fromstring().

Ejemplo:

xml_data = '''
<user>
  <name>Sagawa Shota</name>
  <email>sagawa@example.com</email>
</user>
'''

root = ET.fromstring(xml_data)

name = root.find('name').text
email = root.find('email').text

print(f"Nombre: {name}, Correo: {email}")

De manera similar, se pueden obtener los subelementos necesarios del elemento raíz con find() y extraer sus valores.

Obtención de atributos y manejo de texto

Los elementos XML pueden tener atributos definidos en la etiqueta. En Python, se puede acceder a ellos con .attrib.

Ejemplo (XML con atributos):

<user id="101">
  <name>Sagawa Shota</name>
</user>

Código Python:

root = ET.fromstring('''
<user id="101">
  <name>Shota Sagawa</name>
</user>
''')

print(f"ID de usuario: {root.attrib['id']}")
侍エンジニア塾

3. Introducción a otras bibliotecas de análisis XML

minidom: Biblioteca estándar basada en DOM

xml.dom.minidom es un analizador XML incluido por defecto en Python, que permite manejar XML según la especificación DOM (Document Object Model) del W3C.

Puede dar la impresión de ser un poco más difícil de usar que ElementTree, pero resulta útil cuando se desea manipular detalladamente los tipos y la estructura de los nodos.

Ejemplo:

from xml.dom import minidom

xml_data = '''
<user>
  <name>Sagawa Shota</name>
  <email>sagawa@example.com</email>
</user>
'''

dom = minidom.parseString(xml_data)
name = dom.getElementsByTagName('name')[0].firstChild.nodeValue
email = dom.getElementsByTagName('email')[0].firstChild.nodeValue

print(f"Nombre: {name}, Correo: {email}")

Características y ventajas:

  • Acceso fácil a la estructura detallada de los nodos
  • Los atributos y tipos de nodos hijos están claramente clasificados
  • Facilidad para formatear y emitir XML (pretty print)

Desventajas:

  • El código tiende a ser redundante
  • No es adecuado para procesar XML a gran escala (alto consumo de memoria)

lxml: Biblioteca externa rápida y potente

lxml es un analizador XML rápido implementado en C, que también soporta funciones avanzadas de XML como XPath y XSLT. Proporciona una API similar a ElementTree, por lo que el costo de aprendizaje es bajo.

Método de instalación:

pip install lxml

Uso básico:

from lxml import etree

xml_data = '''
<books>
  <book>
    <title>Python Práctico</title>
    <price>3000</price>
  </book>
</books>
'''

root = etree.fromstring(xml_data)
title = root.xpath('//book/title/text()')[0]
price = root.xpath('//book/price/text()')[0]

print(f"Título: {title}, Precio: {price}yen")

Características y ventajas:

  • Posibilidad de búsquedas flexibles gracias a XPath
  • Adecuado para procesar grandes volúmenes de XML rápidamente
  • Compatibilidad con HTML, útil también para scraping

Desventajas:

  • Requiere instalación de una biblioteca externa
  • Se necesita una pequeña curva de aprendizaje inicial (XPath, etc.)

Resumen de cómo elegir la biblioteca

BibliotecaCaracterísticasCasos adecuados
ElementTreeDisponible en la biblioteca estándar, permite lectura y escritura básicasLectura de XML de pequeña y mediana escala
minidomFuerte en operaciones DOM y excelente en salida formateadaCuando se desea manipular detalladamente la estructura de los nodos
lxmlRápido, compatible con XPath, alta flexibilidadPara datos a gran escala y búsquedas avanzadas

 

4. Código de ejemplo práctico

En esta sección se presenta de forma práctica el procesamiento de lectura de XML con Python, acercándolo a situaciones reales de negocio y procesamiento de datos. Concretamente, se muestran ejemplos de código que cubren patrones comunes como “Iteración de múltiples nodos”, “Filtrado por condición” y “Exportación a archivo XML”, entre otros.

Iteración de múltiples nodos

Si dentro del XML se repiten datos con la misma estructura (por ejemplo, varios elementos ), se utiliza findall() para realizar un bucle.

XML de ejemplo:

<books>
  <book>
    <title>Introducción a Python</title>
    <author>Taro Yamada</author>
    <price>2800</price>
  </book>
  <book>
    <title>El futuro de la IA</title>
    <author>Ichiro Suzuki</author>
    <price>3500</price>
  </book>
</books>

Código Python (usando ElementTree):

import xml.etree.ElementTree as ET

tree = ET.parse('books.xml')
root = tree.getroot()

for book in root.findall('book'):
    title = book.find('title').text
    author = book.find('author').text
    price = int(book.find('price').text)

    print(f"Título: {title}, Autor: {author}, Precio: {price}yen")

De esta manera, al acceder a cada elemento dentro del bucle, se pueden extraer y procesar datos del XML.

Filtrado por condición

A continuación, un procesamiento condicional para extraer solo los libros cuyo precio sea de 3000 yenes o más.

Código Python:

for book in root.findall('book'):
    price = int(book.find('price').text)
    if price >= 3000:
        title = book.find('title').text
        print(f"高額本: {title}({price}円)")

De esta forma, combinando la sentencia if, se pueden manejar solo los elementos que cumplan la condición deseada.

Exportación a archivo XML (guardado)

Es frecuente modificar el XML leído y guardarlo nuevamente como archivo.

Ejemplo de exportación:

# Crear nuevo elemento raíz
root = ET.Element('users')

# Añadir elementos hijos
user1 = ET.SubElement(root, 'user', attrib={'id': '1'})
ET.SubElement(user1, 'name').text = 'Sagawa Shota'
ET.SubElement(user1, 'email').text = 'sagawa@example.com'

# Guardar como estructura de árbol
tree = ET.ElementTree(root)
tree.write('users.xml', encoding='utf-8', xml_declaration=True)

Con esto se genera un archivo XML como el siguiente:

<?xml version='1.0' encoding='utf-8'?>
<users>
  <user id="1">
    <name>Sagawa Shota</name>
    <email>sagawa@example.com</email>
  </user>
</users>

Aplicación: extracción con XPath (lxml)

Si se está usando lxml, es posible realizar búsquedas más flexibles y potentes.

from lxml import etree

tree = etree.parse('books.xml')
titles = tree.xpath('//book[price >= 3000]/title/text()')

for title in titles:
    print(f"Título de libro caro: {title}")

Al aprovechar XPath, se pueden extraer datos de forma intuitiva incluso con condiciones complejas.

年収訴求

5. Errores comunes y soluciones

Al leer XML con Python, pueden ocurrir varios errores, como errores de sintaxis o problemas de codificación de caracteres. En esta sección se presentan los errores típicos que suelen atrapar a los principiantes y sus soluciones.

UnicodeDecodeError: fallo de lectura por diferencia de codificación

Detalle del error:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x93 in position 10

Causa:
Si el archivo XML está guardado con una codificación distinta a UTF-8 (por ejemplo Shift_JIS o UTF-16), Python no podrá decodificarlo correctamente y se producirá un error.

Solución:
Especifique explícitamente la codificación al leer el archivo.

with open('sample.xml', encoding='shift_jis') as f:
    data = f.read()

import xml.etree.ElementTree as ET
root = ET.fromstring(data)

También es válido pasar directamente en modo binario a ElementTree.parse().

ParseError: sintaxis XML inválida

Detalle del error:

xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 3, column 15

Causa:
Ocurre cuando alguna etiqueta del archivo XML no está cerrada, caracteres especiales (p.ej. &) no están escapados, o hay errores de sintaxis.

Solución:

  • Identificar la línea y columna correspondientes a partir del mensaje de error
  • Usar el editor para formatear y revisar errores de sintaxis en el XML
  • Convertir caracteres especiales (p.ej. &&)

Ejemplo: XML incorrecto

<note>
  <text>5 & 3</text>
</note>

Después de la corrección:

<note>
  <text>5 &amp; 3</text>
</note>

NoneType Attribute Error: acceso a elemento inexistente

Detalle del error:

AttributeError: 'NoneType' object has no attribute 'text'

Causa:
Si la etiqueta especificada no existe en el XML, find() devuelve None y al acceder directamente a .text se produce un error.

Solución:
Compruebe si el elemento existe antes de obtener su valor.

title_elem = book.find('title')
if title_elem is not None:
    title = title_elem.text
else:
    title = 'Título desconocido'

También, si usa Python 3.8 o superior, puede emplear el operador walrus (:=) para escribir de forma concisa.

if (title_elem := book.find('title')) is not None:
    print(title_elem.text)

XML file corrupto o vacío

Síntomas:

  • No se produce error, pero getroot() devuelve None
  • findall() no devuelve nada

Causa:

  • El archivo XML está vacío (0 bytes)
  • Los datos están truncados (fallo de descarga, etc.)

Solución:

  • Verificar el tamaño y contenido del archivo
  • Ejecutar una validación de sintaxis con una herramienta de validación XML
  • Revisar el proceso de origen de descarga o generación

6. Preguntas frecuentes (FAQ)

En esta sección, explicamos de forma clara en formato Q&A las dudas y preocupaciones más frecuentes de los lectores que desean “leer XML con Python”. El contenido está pensado para resolver de antemano los puntos donde es fácil tropezar en el trabajo o el aprendizaje.

Q1. ¿Cómo manejar la codificación (charset) de los archivos XML?

A.
Los archivos XML normalmente incluyen una especificación de codificación en la parte superior, como la siguiente:

<?xml version="1.0" encoding="UTF-8"?>

Python’s ElementTree y lxml automáticamente leen esta declaración, pero si la codificación no coincide al abrir el archivo, se producirá un error.

En archivos XML en japonés, a veces se usan Shift_JIS o EUC-JP, por lo que es seguro especificar explícitamente la codificación de la siguiente manera:

with open('sample.xml', encoding='shift_jis') as f:
    data = f.read()

Además, al usar lxml el manejo de la codificación es más flexible.

Q2. ¿Qué hacer cuando procesar archivos XML gigantes causa falta de memoria?

A.
Si se carga un XML de gran tamaño de una sola vez, se despliega todo en la memoria, lo que puede hacer que el procesamiento sea lento o que se produzca un error.

En esos casos, es eficaz usar un “parser tipo iterador” que pueda leer de forma secuencial.

import xml.etree.ElementTree as ET

for event, elem in ET.iterparse('large.xml', events=('end',)):
    if elem.tag == 'book':
        print(elem.find('title').text)
        elem.clear()  # Liberar memoria

Con este método, solo se procesa la parte necesaria en orden, lo que ahorra memoria.

Q3. ¿Cuáles son los beneficios de usar XML en lugar de JSON?

A.
Hoy en día, muchas API utilizan JSON, pero XML también tiene sus propias fortalezas.

  • Permite definir estrictamente la estructura jerárquica (DTD/XSD, etc.)
  • Posibilidad de diferenciar atributos y elementos
  • Fuerte orientación a documentos, adecuada para archivos de configuración e información estructurada
  • En sistemas de empresas y gobiernos locales, XML sigue siendo dominante

En resumen, XML sobresale más en definir documentos estructurados que en ser leído por personas. Dependiendo del caso de uso, seguirá siendo relevante en el futuro.

Q4. ¿Cuál debería usar, lxml o ElementTree?

A.
Es conveniente elegir según los siguientes criterios:

BibliotecaCasos adecuados
ElementTreeXML de pequeña‑mediana escala, cuando la biblioteca estándar es suficiente
lxmlCuando se desea usar XPath, se necesita alta velocidad o se manejan grandes volúmenes de datos

Para principiantes se recomienda comenzar con ElementTree, pero en casos que requieren velocidad de procesamiento y extracción flexible con XPath, lxml es potente.

7. Resumen

En este artículo, hemos explicado “Cómo leer XML con Python” de forma que sea fácil de entender para principiantes y, al mismo tiempo, fácil de aplicar en entornos profesionales.

La lectura de XML con Python es sorprendentemente simple

Si utilizas la biblioteca estándar xml.etree.ElementTree, puedes leer XML de inmediato sin preparación especial. Una vez que aprendas la sintaxis básica y los métodos (parse(), find(), findall(), etc.), será fácil obtener y procesar los datos.

Es importante elegir la biblioteca adecuada según el caso de uso

  • Procesamiento pequeño y simple:ElementTree
  • Operaciones detalladas de nodos y salida formateada:minidom
  • Procesamiento rápido y búsqueda XPath:lxml

Cada una tiene sus ventajas y desventajas, así que elige según el tamaño y el propósito del XML que manejes.

Prepárate para los errores y problemas comunes

Incluso los errores en los que los principiantes suelen tropezar no serán un problema si comprendes sus causas y soluciones. En particular, los “diferentes juegos de caracteres”, los “errores de sintaxis” y la “verificación de existencia de elementos” son frecuentes.

XML sigue siendo una tecnología vigente

Aunque el uso de JSON ha aumentado recientemente, XML todavía se utiliza en muchos sistemas empresariales, gubernamentales y en intercambios de datos. Dominar el procesamiento de XML con Python se convierte en una habilidad útil en una amplia gama de campos.

RUNTEQ(ランテック)|超実戦型エンジニア育成スクール