Domanda

Python ha diversi modi per analizzare XML ...

Comprendo le basi dell'analisi con SAX . Funziona come un parser di flusso, con un'API guidata dagli eventi.

Comprendo anche il parser DOM . Legge l'XML in memoria e lo converte in oggetti a cui è possibile accedere con Python.

In generale, era facile scegliere tra i due a seconda di cosa dovevi fare, vincoli di memoria, prestazioni, ecc.

(Spero di aver ragione fino ad ora.)

Da Python 2.5, abbiamo anche ElementTree . Come si confronta con DOM e SAX? A cosa è più simile? Perché è meglio dei precedenti parser?

È stato utile?

Soluzione

ElementTree è molto più facile da usare, perché rappresenta un albero XML (sostanzialmente) come una struttura di elenchi e gli attributi sono rappresentati come dizionari.

ElementTree richiede molta meno memoria per gli alberi XML rispetto al DOM (e quindi è più veloce), e l'overhead di analisi tramite iterparse è paragonabile a SAX. Inoltre, iterparse restituisce strutture parziali e puoi mantenere costante l'uso della memoria durante l'analisi scartando le strutture non appena le elabori.

ElementTree, come in Python 2.5, ha solo un piccolo set di funzionalità rispetto alle librerie XML complete, ma è sufficiente per molte applicazioni. Se hai bisogno di un parser di convalida o di un supporto XPath completo, lxml è la strada da percorrere. Per molto tempo, era piuttosto instabile, ma non ho avuto problemi con esso dal 2.1.

ElementTree si discosta dal DOM, dove i nodi hanno accesso ai loro genitori e fratelli. Anche la gestione di documenti effettivi anziché di archivi di dati è un po 'complicata, poiché i nodi di testo non sono trattati come nodi effettivi. Nello snippet XML

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

La stringa test sarà la cosiddetta tail dell'elemento b .

In generale, consiglio ElementTree come predefinito per tutta l'elaborazione XML con Python e DOM o SAX come soluzioni per problemi specifici.

Altri suggerimenti

Implementazione DOM minima:

Link .

Python fornisce un'implementazione completa, standard W3C di XML DOM ( xml.dom ) e minima, xml.dom.minidom . Quest'ultimo è più semplice e più piccolo della piena implementazione. Tuttavia, dal punto di vista dell'analisi, ha tutti i vantaggi e gli svantaggi del DOM standard, ovvero carica tutto in memoria.

Considerando un file XML di 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 possibile parser Python che utilizza minidom è:

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

Nota che xml.parsers.expat è un'interfaccia Python per il parser XML non validante Expat (docs.python.org/2/library/pyexpat.html).

Il pacchetto xml.dom fornisce anche la classe di eccezioni DOMException , ma non è supportata in minidom !

L'API XML ElementTree:

Link .

ElementTree è molto più facile da usare e richiede meno memoria del DOM XML. Inoltre, è disponibile un'implementazione C ( xml.etree.cElementTree ).

Un possibile parser Python che utilizza ElementTree è:

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

L'analisi () di ElementTree è come DOM, mentre iterparse () è come SAX. A mio avviso, ElementTree è migliore di DOM e SAX in quanto fornisce API più facile da lavorare.

ElementTree ha più API pythonic. Ora è anche nella libreria standard, quindi l'utilizzo riduce le dipendenze.

In realtà preferisco lxml in quanto ha API come ElementTree, ma ha anche belle funzionalità aggiuntive e funziona bene.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top