web-dev-qa-db-fra.com

Analyse XML - ElementTree vs SAX et DOM

Python a plusieurs façons d'analyser XML ...

Je comprends les bases de l'analyse syntaxique avec SAX . Il fonctionne comme un analyseur de flux, avec une API événementielle.

Je comprends également l'analyseur DOM . Il lit le XML dans la mémoire et le convertit en objets accessibles avec Python.

D'une manière générale, il était facile de choisir entre les deux en fonction de ce que vous deviez faire, des contraintes de mémoire, des performances, etc.

(J'espère que j'ai raison jusqu'à présent.)

Depuis Python 2.5, nous avons également ElementTree. Comment cela se compare-t-il à DOM et SAX? À quoi est-il plus similaire? Pourquoi est-il meilleur que les analyseurs précédents?

67
Corey Goldberg

ElementTree est beaucoup plus facile à utiliser, car il représente une arborescence XML (essentiellement) comme une structure de listes, et les attributs sont représentés comme des dictionnaires.

ElementTree a besoin de beaucoup moins de mémoire pour les arborescences XML que DOM (et est donc plus rapide), et la surcharge d'analyse via iterparse est comparable à SAX. De plus, iterparse renvoie des structures partielles et vous pouvez maintenir l'utilisation de la mémoire constante pendant l'analyse en ignorant les structures dès que vous les traitez.

ElementTree, comme dans Python 2.5, n'a qu'un petit ensemble de fonctionnalités par rapport aux bibliothèques XML complètes, mais cela suffit pour de nombreuses applications. Si vous avez besoin d'un analyseur de validation ou d'un support XPath complet, lxml est Pendant longtemps, il était assez instable, mais je n'ai eu aucun problème avec lui depuis la 2.1.

ElementTree diffère du DOM, où les nœuds ont accès à leur parent et à leurs frères et sœurs. La gestion des documents réels plutôt que des magasins de données est également un peu lourde, car les nœuds de texte ne sont pas traités comme des nœuds réels. Dans l'extrait XML

<a>This is <b>a</b> test</a>

La chaîne test sera le soi-disant tail de l'élément b.

En général, je recommande ElementTree comme valeur par défaut pour tous les traitements XML avec Python, et DOM ou SAX comme solutions pour des problèmes spécifiques.

65
Torsten Marek

Implémentation DOM minimale:

Lien .

Python fournit une implémentation complète, conforme au W3C, de XML DOM ( xml.dom ) et une version minimale, xml .dom.minidom . Cette dernière est plus simple et plus petite que l'implémentation complète. Cependant, d'un "point de vue d'analyse", il a tous les avantages et les inconvénients du DOM standard - c'est-à-dire qu'il charge tout en mémoire.

Considérant un fichier XML de base:

<?xml version="1.0"?>
<catalog>
    <book isdn="xxx-1">
      <author>A1</author>
      <title>T1</title>
    </book>
    <book isdn="xxx-2">
      <author>A2</author>
      <title>T2</title>
    </book>
</catalog>

Un possible Python utilisant minidom est:

import os
from xml.dom import minidom
from xml.parsers.expat import ExpatError

#-------- Select the XML file: --------#
#Current file name and directory:
curpath = os.path.dirname( os.path.realpath(__file__) )
filename = os.path.join(curpath, "sample.xml")
#print "Filename: %s" % (filename)

#-------- Parse the XML file: --------#
try:
    #Parse the given XML file:
    xmldoc = minidom.parse(filepath)
except ExpatError as e:
    print "[XML] Error (line %d): %d" % (e.lineno, e.code)
    print "[XML] Offset: %d" % (e.offset)
    raise e
except IOError as e:
    print "[IO] I/O Error %d: %s" % (e.errno, e.strerror)
    raise e
else:
    catalog = xmldoc.documentElement
    books = catalog.getElementsByTagName("book")

    for book in books:
        print book.getAttribute('isdn')
        print book.getElementsByTagName('author')[0].firstChild.data
        print book.getElementsByTagName('title')[0].firstChild.data

Notez que xml.parsers.expat est une interface Python avec l'analyseur XML non valide Expat (docs.python) .org/2/library/pyexpat.html).

Le package xml.dom fournit également la classe d'exception DOMException , mais il n'est pas supposé dans minidom !

L'API XML ElementTree:

Lien .

ElementTree est beaucoup plus facile à utiliser et nécessite moins de mémoire que XML DOM. De plus, une implémentation C est disponible ( xml.etree.cElementTree ).

Un possible Python utilisant ElementTree est:

import os
from xml.etree import cElementTree  # C implementation of xml.etree.ElementTree
from xml.parsers.expat import ExpatError  # XML formatting errors

#-------- Select the XML file: --------#
#Current file name and directory:
curpath = os.path.dirname( os.path.realpath(__file__) )
filename = os.path.join(curpath, "sample.xml")
#print "Filename: %s" % (filename)

#-------- Parse the XML file: --------#
try:
    #Parse the given XML file:
    tree = cElementTree.parse(filename)
except ExpatError as e:
    print "[XML] Error (line %d): %d" % (e.lineno, e.code)
    print "[XML] Offset: %d" % (e.offset)
    raise e
except IOError as e:
    print "[XML] I/O Error %d: %s" % (e.errno, e.strerror)
    raise e
else:
    catalogue = tree.getroot()

    for book in catalogue:
        print book.attrib.get("isdn")
        print book.find('author').text
        print book.find('title').text
13
Paolo Rovelli

Parse () d'ElementTree est comme DOM, tandis que iterparse () est comme SAX. À mon avis, ElementTree est meilleur que DOM et SAX dans la mesure où il fournit une API plus facile à utiliser.

7
sanxiyn

ElementTree a plus d'API Pythonic. Il se trouve également dans la bibliothèque standard maintenant, donc son utilisation réduit les dépendances.

En fait, je préfère lxml car il a une API comme ElementTree, mais a également de belles fonctionnalités supplémentaires et fonctionne bien.

7
iny