Синтаксический анализ XML - ElementTree против SAX и DOM - PullRequest
68 голосов
/ 11 октября 2008

В Python есть несколько способов разбора XML ...

Я понимаю основы синтаксического анализа с SAX . Он работает как анализатор потока с API, управляемым событиями.

Я также понимаю парсер DOM . Он читает XML в память и преобразует его в объекты, к которым можно получить доступ с помощью Python.

Вообще говоря, было легко выбирать между ними в зависимости от того, что вам нужно сделать, ограничений памяти, производительности и т. Д.

(Надеюсь, я пока прав).

Начиная с Python 2.5, у нас также есть ElementTree . Как это соотносится с DOM и SAX? На что это больше похоже? Чем он лучше предыдущих парсеров?

Ответы [ 4 ]

65 голосов
/ 11 октября 2008

ElementTree намного проще в использовании, поскольку он представляет дерево XML (в основном) в виде структуры списков, а атрибуты представлены в виде словарей.

ElementTree требует гораздо меньше памяти для деревьев XML, чем DOM (и, следовательно, быстрее), а затраты на синтаксический анализ с помощью iterparse сопоставимы с SAX. Кроме того, iterparse возвращает частичные структуры, и вы можете поддерживать постоянное использование памяти во время синтаксического анализа, отбрасывая структуры, как только вы их обрабатываете.

ElementTree, как и в Python 2.5, имеет лишь небольшой набор функций по сравнению с полноценными библиотеками XML, но этого достаточно для многих приложений. Если вам нужен проверяющий синтаксический анализатор или полная поддержка XPath, лучше использовать lxml. Долгое время он был довольно нестабильным, но у меня не было проблем с ним с 2.1.

ElementTree отклоняется от DOM, где узлы имеют доступ к своим родителям и братьям и сестрам. Работа с реальными документами, а не с хранилищами данных также немного обременительна, поскольку текстовые узлы не рассматриваются как фактические узлы. В фрагменте XML

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

Строка test будет так называемым tail элемента b.

В общем, я рекомендую ElementTree по умолчанию для всей обработки XML с Python, а DOM или SAX в качестве решения для конкретных проблем.

13 голосов
/ 16 марта 2013

Минимальная реализация DOM:

Ссылка .

Python предоставляет полную W3C-стандартную реализацию XML DOM ( xml.dom ) и минимальную xml.dom.minidom . Этот последний проще и меньше, чем полная реализация. Однако с «точки зрения синтаксического анализа» у него есть все плюсы и минусы стандартного DOM - то есть он загружает все в память.

Рассматривая базовый XML-файл:

<?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>

Возможный парсер Python, использующий 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

Обратите внимание, что xml.parsers.expat - это интерфейс Python для XML-парсера Expat без проверки (docs.python.org/2/library/pyexpat.html).

Пакет xml.dom также предоставляет класс исключений DOMException , но он не поддерживается в minidom !

API ElementTree XML:

Ссылка .

ElementTree намного проще в использовании и требует меньше памяти, чем XML DOM. Кроме того, доступна реализация C ( xml.etree.cElementTree ).

Возможный парсер Python, использующий 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
8 голосов
/ 11 октября 2008

ElementTree parse () похож на DOM, тогда как iterparse () похож на SAX. На мой взгляд, ElementTree лучше, чем DOM и SAX в том смысле, что он обеспечивает API, с которым легче работать.

7 голосов
/ 11 октября 2008

ElementTree имеет более питонский API. Теперь он также находится в стандартной библиотеке, поэтому его использование уменьшает зависимости.

Я на самом деле предпочитаю lxml , поскольку он имеет API-интерфейс, такой как ElementTree, но также имеет хорошие дополнительные функции и хорошо работает.

...