ElementTree と xpath を使用して、xml ファイル内の特定の要素のテキスト コンテンツを抽出する小さな関数を作成しました。
#!/usr/bin/env python2.5
import doctest
from xml.etree import ElementTree
from StringIO import StringIO
def parse_xml_etree(sin, xpath):
"""
Takes as input a stream containing XML and an XPath expression.
Applies the XPath expression to the XML and returns a generator
yielding the text contents of each element returned.
>>> parse_xml_etree(
... StringIO('<test><elem1>one</elem1><elem2>two</elem2></test>'),
... '//elem1').next()
'one'
>>> parse_xml_etree(
... StringIO('<test><elem1>one</elem1><elem2>two</elem2></test>'),
... '//elem2').next()
'two'
>>> parse_xml_etree(
... StringIO('<test><null>�</null><elem3>three</elem3></test>'),
... '//elem2').next()
'three'
"""
tree = ElementTree.parse(sin)
for element in tree.findall(xpath):
yield element.text
if __name__ == '__main__':
doctest.testmod(verbose=True)
3 番目のテストは、次の例外で失敗します。
ExpatError: 無効な文字番号への参照: 行 1、列 13
�
エンティティは違法な XML ですか? そうであるかどうかに関係なく、解析したいファイルにはそれが含まれており、それらを解析する方法が必要です。それを可能にする Expat 以外のパーサー、または Expat の設定に関する提案はありますか?
更新:私はちょうど今BeautifulSoupを発見しました。これは、以下の回答のコメントに記載されているタグスープパーサーであり、楽しみのためにこの問題に戻り、ElementTree の前で XML クリーナーとして使用しようとしましたが、忠実にに変換さ�
れました。まったく無効な null バイト。:-)
cleaned_s = StringIO(
BeautifulStoneSoup('<test><null>�</null><elem3>three</elem3></test>',
convertEntities=BeautifulStoneSoup.XML_ENTITIES
).renderContents()
)
tree = ElementTree.parse(cleaned_s)
... 収量
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 12
ただし、私の特定のケースでは、XPath 解析自体は実際には必要ありませんでした。BeautifulSoup 自体とその非常に単純なノード アドレッシング スタイルを使用することもできたはずparsed_tree.test.elem1.contents[0]
です。