XML structure des données sous forme d’arborescence, avec des balises imbriquées qui décrivent à la fois le contenu et sa hiérarchie. Python dispose de plusieurs modules pour lire, parcourir et extraire ces données sans écrire de logique de parsing manuel. Cet article explique comment parse XML using Python en partant de la bibliothèque standard, puis en élargissant aux cas où le document provient du web.
Structure d’un document XML : balises, éléments et attributs
Un document XML repose sur une arborescence. Chaque noeud est un element délimité par une balise ouvrante et une balise fermante. Un element peut contenir du texte, des attributs (paires clé-valeur dans la balise ouvrante) et d’autres elements enfants.
A découvrir également : Ce qui façonne le développement web en 2024
Prenons un exemple minimal que le reste de l’article réutilisera :
<catalog><book id="1"><title>Python Data</title><price>29.99</price></book><book id="2"><title>Web Scraping</title><price>34.50</price></book></catalog>
A lire aussi : Installing Python with pip pour la data science : installer les bons modules
Ici, catalog est l’element racine. Chaque book possède un attribut id et deux enfants : title et price. Comprendre cette hiérarchie est le prérequis avant d’écrire la moindre ligne de code Python.
Parser du XML avec ElementTree en Python
Le module xml.etree.ElementTree fait partie de la bibliothèque standard. Aucune installation supplémentaire. Il couvre la majorité des besoins pour du XML bien formé.
Charger le document
Deux fonctions d’entrée existent : ET.parse() pour un fichier local, ET.fromstring() pour une chaîne de caractères. Dans les deux cas, le résultat donne accès à l’element racine.
import xml.etree.ElementTree as ETtree = ET.parse('catalog.xml')root = tree.getroot()
La variable root est un objet Element. À partir de là, tout le parcours se fait par itération sur les enfants.
Parcourir et extraire avec find et iter
La méthode find retourne le premier element correspondant au tag cherché. findall retourne une liste. iter parcourt récursivement toute l’arborescence.
for book in root.findall('book'): title = book.find('title').text price = book.find('price').text book_id = book.get('id')
La propriété .text récupère le contenu textuel d’un element. La méthode .get() récupère la valeur d’un attribut. Ce duo couvre la plupart des extractions courantes.

Traiter du XML récupéré depuis le web avec requests
Beaucoup de flux de donnees (RSS, API publiques, sitemaps) servent du XML via une URL. Le module requests télécharge le contenu, puis ElementTree le parse.
import requestsresponse = requests.get('https://example.com/feed.xml')root = ET.fromstring(response.content)
Deux points à surveiller ici. D’abord, utiliser response.content (bytes) plutôt que response.text (str) pour laisser le parser gérer l’encodage déclaré dans le document XML. Ensuite, vérifier le code HTTP avant de parser :
if response.status_code == 200: root = ET.fromstring(response.content)
Cette approche fonctionne pour tout document XML accessible par URL, y compris les sitemaps de page web que l’on souhaite analyser.
BeautifulSoup pour du XML mal formé ou mixte HTML-XML
ElementTree exige un document XML strictement valide. Face à du contenu mal formé, des balises non fermées ou un mélange HTML/XML, BeautifulSoup (module beautifulsoup4, souvent importé sous bs4) offre une tolérance bien supérieure.
from bs4 import BeautifulSoupsoup = BeautifulSoup(xml_content, 'lxml-xml')
Le parser lxml-xml traite le contenu comme du XML. Pour du HTML, on utiliserait 'html.parser' ou 'lxml'. La distinction est réelle : le mode XML respecte la casse des balises, le mode HTML la normalise.
Naviguer dans le soup
BeautifulSoup expose des méthodes proches d’ElementTree mais avec une syntaxe légèrement différente :
soup.find('title')retourne le premier elementtitletrouvé, comme un appelfindclassiquesoup.find_all('book')renvoie une liste de tous les elementsbookdu documentelement.get_text()extrait le contenu text d’un element, en ignorant les balises enfantselement['id']accède directement à un attribut, comme un dictionnaire Python
Pour du scraper de flux RSS ou de pages web hybrides, BeautifulSoup reste le choix le plus pragmatique. La contrepartie : il faut installer beautifulsoup4 et lxml via pip, là où ElementTree ne demande rien.
Erreurs fréquentes quand on débute le parsing XML en Python
Certaines erreurs reviennent systématiquement lors des premiers essais. Les identifier en amont fait gagner du temps.
- Oublier les namespaces XML : beaucoup de documents déclarent un namespace par défaut. Sans le préfixer dans les appels
findoufindall, ElementTree ne trouve aucun element. La syntaxe estroot.findall('{http://namespace-uri}tag') - Confondre
.textet.tail: dans ElementTree, le texte qui suit la balise fermante d’un element (avant la balise suivante) est stocké dans.tail, pas dans.text. Ignorer cette distinction produit des extractions incomplètes - Parser du HTML avec un parser XML : un document HTML classique n’est presque jamais du XML valide. ElementTree lèvera une exception. Il faut alors passer par BeautifulSoup avec le parser html adapté

Choisir entre ElementTree et BeautifulSoup pour parser du XML
Le choix dépend du document source. ElementTree convient pour du XML propre, généré par une application ou un service structuré (API REST, fichiers de configuration, sitemaps). Aucune dépendance externe, performance correcte, code lisible.
BeautifulSoup prend le relais quand le document est douteux : flux RSS mal encodés, contenu mixte récupéré par un scraper, pages web converties. Sa tolérance aux erreurs de balisage justifie la dépendance supplémentaire.
Dans un projet data, les deux cohabitent sans problème. ElementTree pour les sources fiables, BeautifulSoup pour tout le reste. La logique d’extraction (boucle for, appels find, accès au text et aux attributs) reste quasiment identique d’un module à l’autre, ce qui facilite le passage de l’un à l’autre selon le type de document rencontré.

