79

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

SAXによる構文解析の基本を理解しています。イベント駆動型 API を使用して、ストリーム パーサーとして機能します。

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

一般的に言えば、実行する必要があること、メモリの制約、パフォーマンスなどに応じて、2 つのいずれかを選択するのは簡単でした。

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

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

4

4 に答える 4

79

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は、いわゆるtailof element になりbます。

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

于 2008-10-11T16:02:41.003 に答える
14

最小限の DOM 実装:

リンク

Python は、XML DOM ( xml.dom ) の完全な W3C 標準実装と、最小限の実装である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>

minidomを使用できる Python パーサーは次のとおりです。

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は、Expat 非検証 XML パーサー (docs.python.org/2/library/pyexpat.html) への Python インターフェースであることに注意してください。

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

ElementTree XML API:

リンク

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

ElementTreeを使用できる Python パーサーは次のとおりです。

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
于 2013-03-16T17:33:15.727 に答える
8

ElementTree has more pythonic API. It also is in the standard library now so using it reduces dependencies.

I actually prefer lxml as it has API like ElementTree, but has also nice additional features and performs well.

于 2008-10-11T15:24:41.457 に答える
7

ElementTree の parse() は DOM に似ていますが、iterparse() は SAX に似ています。私の意見では、ElementTree は DOM や SAX よりも優れており、API の操作が簡単です。

于 2008-10-10T20:25:05.343 に答える