5

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>&#0;</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

&#0;エンティティは違法な XML ですか? そうであるかどうかに関係なく、解析したいファイルにはそれが含まれており、それらを解析する方法が必要です。それを可能にする Expat 以外のパーサー、または Expat の設定に関する提案はありますか?


更新:私はちょうど今BeautifulSoupを発見しました。これは、以下の回答のコメントに記載されているタグスープパーサーであり、楽しみのためにこの問題に戻り、ElementTree の前で XML クリーナーとして使用しようとしましたが、忠実にに変換さ&#0;れました。まったく無効な null バイト。:-)

cleaned_s = StringIO(
  BeautifulStoneSoup('<test><null>&#0;</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]です。

4

2 に答える 2

6

&#0;XML 仕様で定義されている有効な文字範囲内にありません。残念ながら、私の Python スキルはかなり初歩的なものなので、あまり役に立ちません。

于 2010-06-14T16:13:38.100 に答える
4

&#0;は有効な XML 文字ではありません。理想的には、ファイルの作成者にプロセスを変更してもらい、ファイルがこのように無効にならないようにすることができます。

これらのファイルを受け入れる必要がある場合は、それらを前処理して別の&#0ものに変えることができます。たとえば、@ をエスケープ文字として選択し、"@" を "@@" に、" &#0;" を "@0" に変換します。

次に、パーサーからテキスト データを取得すると、マッピングを逆にすることができます。これは単なる例であり、好きなエスケープ構文を作成できます。

于 2010-06-14T16:23:54.523 に答える