lxml * を使用すると、parse()
およびtostring()
関数を使用してかなり簡単に実行できます。
from lxml.etree import parse, tostring
まず、ドキュメントを解析して要素を取得します (私は XPath を使用していますが、好きなものを使用できます)。
doc = parse('test.xml')
element = doc.xpath('//text')[0]
このtostring()
関数は、要素のテキスト表現を返します。
>>> tostring(element)
'<text>Some <text>text</text> with <extradata>data</extradata> in it.</text>\n'
ただし、外部要素は必要ないため、簡単なstr.replace()
呼び出しで削除できます。
>>> tostring(element).replace('<%s>'%element.tag, '', 1)
'Some <text>text</text> with <extradata>data</extradata> in it.</text>\n'
str.replace()
3 番目のパラメーターとして 1 を受け取ったため、最初に出現した開始タグのみが削除されることに注意してください。終了タグでもできます。ここで、1 の代わりに -1 を渡して置き換えます。
>>> tostring(element).replace('</%s>'%element.tag, '', -1)
'<text>Some <text>text with <extradata>data</extradata> in it.\n'
もちろん、解決策はすべてを一度に行うことです。
>>> tostring(element).replace('<%s>'%element.tag, '', 1).replace('</%s>'%element.tag, '', -1)
'Some <text>text with <extradata>data</extradata> in it.\n'
編集: @Charles は良い点を指摘しました: タグは属性を持つことができるため、このコードは脆弱です。可能なまだ限定的な解決策は、文字列を最初に分割すること>
です。
>>> tostring(element).split('>', 1)
['<text',
'Some <text>text</text> with <extradata>data</extradata> in it.</text>\n']
2 番目の結果の文字列を取得します。
>>> tostring(element).split('>', 1)[1]
'Some <text>text</text> with <extradata>data</extradata> in it.</text>\n'
次にそれを分割します:
>>> tostring(element).split('>', 1)[1].rsplit('</', 1)
['Some <text>text</text> with <extradata>data</extradata> in it.', 'text>\n']
そして最後に最初の結果を取得します:
>>> tostring(element).split('>', 1)[1].rsplit('</', 1)[0]
'Some <text>text</text> with <extradata>data</extradata> in it.'
>
とはいえ、属性内であっても XML では完全に有効な char であるため、このコードはまだ脆弱です。
いずれにせよ、MattH ソリューションが実際の一般的なソリューションであることを認めなければなりません。
* 実際、このソリューションはElementTreeでも機能します。これは、lxml に依存したくない場合に最適です。唯一の違いは、XPath を使用する方法がないことです。