web-dev-qa-db-ja.com

XML解析-ElementTree対SAXおよびDOM

Pythonには、XMLを解析する方法がいくつかあります...

[〜#〜] sax [〜#〜]で解析の基本を理解しています。イベント駆動型APIを備えたストリームパーサーとして機能します。

[〜#〜] dom [〜#〜]パーサーも理解しています。 XMLをメモリに読み取り、Pythonでアクセスできるオブジェクトに変換します。

一般的に言えば、何をする必要があるか、メモリの制約、パフォーマンスなどに応じて2つから簡単に選択できました。

(うまくいけば、私は今のところ正しいです。)

Python 2.5なので、ElementTreeもあります。これはDOMやSAXと比較してどうですか?どちらがより似ていますか?以前のパーサーよりも優れているのはなぜですか?]

67
Corey Goldberg

ElementTreeはXMLツリーを(基本的に)リストの構造として表し、属性は辞書として表されるため、使いやすくなっています。

ElementTreeはDOMよりもXMLツリーに必要なメモリがはるかに少なく(したがって高速です)、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になります。

一般に、Pythonを使用したすべてのXML処理のデフォルトとしてElementTreeを、特定の問題の解決策としてDOMまたはSAXをお勧めします。

65
Torsten Marek

最小限のDOM実装:

リンク

Pythonは、XML DOMの完全なW3C標準実装(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>

可能なPythonminidomを使用したパーサーは:

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 Expat非検証XMLパーサー(docs.python .org/2/library/pyexpat.html)。

xml.domパッケージは例外クラスDOMExceptionも提供しますが、 minidomには含まれていません!

ElementTree XML API:

リンク

ElementTreeははるかに使いやすく、XML DOMよりも少ないメモリで済みます。さらに、C実装が利用可能です(xml.etree.cElementTree)。

可能なPythonElementTreeを使用したパーサーは:

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

ElementTreeのparse()はDOMに似ていますが、iterparse()はSAXに似ています。私の意見では、ElementTreeは操作しやすいAPIを提供するという点でDOMやSAXよりも優れています。

7
sanxiyn

ElementTreeにはより多くのPythonic APIがあります。また、現在標準ライブラリに含まれているため、使用することで依存関係が軽減されます。

ElementTreeのようなAPIを持っているので、実際には lxml を好みますが、ニースの追加機能もあり、うまく機能します。

7
iny