9

Python の ElementTree を使用して、ノードからすべてのテキストを抽出し、その要素のタグを削除してテキストのみを保持するにはどうすればよいですか?

たとえば、次のものがあるとします。

<tag>
  Some <a>example</a> text
</tag>

戻りたいですSome example text。どうすればこれを行うことができますか?これまでのところ、私が取ったアプローチはかなり悲惨な結果をもたらしました。

4

3 に答える 3

22

Python 3.2+ で実行している場合は、itertext.

itertextこの要素とすべてのサブ要素をドキュメント順にループするテキスト反復子を作成し、すべての内部テキストを返します。

import xml.etree.ElementTree as ET
xml = '<tag>Some <a>example</a> text</tag>'
tree = ET.fromstring(xml)
print(''.join(tree.itertext()))

# -> 'Some example text'

下位バージョンの Python で実行している場合は、クラスにアタッチすることでの実装を再利用できます。その後、上記とまったく同じように呼び出すことができます。itertext()Element

# original implementation of .itertext() for Python 2.7
def itertext(self):
    tag = self.tag
    if not isinstance(tag, basestring) and tag is not None:
        return
    if self.text:
        yield self.text
    for e in self:
        for s in e.itertext():
            yield s
        if e.tail:
            yield e.tail

# if necessary, monkey-patch the Element class
if 'itertext' not in ET.Element.__dict__:
    ET.Element.itertext = itertext

xml = '<tag>Some <a>example</a> text</tag>'
tree = ET.fromstring(xml)
print(''.join(tree.itertext()))

# -> 'Some example text'
于 2013-10-14T22:07:32.727 に答える
5

ドキュメントにあるように、中間タグなしでテキストのみを読みたい場合は、すべての属性texttail属性を正しい順序で再帰的に連結する必要があります。

ただし、最近の十分なバージョン (2.7 および 3.2 の stdlib のものを含みますが、2.6 または 3.1 のものは含まれず、現在リリースされている両方のバージョンとElementTreePyPIlxmlのバージョン) は、tostringメソッドで自動的にこれを行うことができます。

>>> s = '''<tag>
...   Some <a>example</a> text
... </tag>'''
>>> t = ElementTree.fromstring(s)
>>> ElementTree.tostring(s, method='text')
'\n  Some example text\n'

テキストから空白も取り除きたい場合は、手動で行う必要があります。あなたの単純なケースでは、それは簡単です:

>>> ElementTree.tostring(s, method='text').strip()
'Some example text'

ただし、中間タグ内の空白を取り除きたい、より複雑なケースでは、おそらくtexts とtails を再帰的に処理する必要があります。それほど難しいことではありません。属性がNone. たとえば、独自のコードをフックできるスケルトンは次のとおりです。

def textify(t):
    s = []
    if t.text:
        s.append(t.text)
    for child in t.getchildren():
        s.extend(textify(child))
    if t.tail:
        s.append(t.tail)
    return ''.join(s)

このバージョンは、 および が または であることが保証されている場合にのみtext機能しtailます。手動で構築したツリーの場合、それが正しいとは限りません。strNone

于 2013-10-14T21:59:00.920 に答える