UTF-8でElementTreeを書き出す方法

私は生成した巨大な(50MB)XML ElementTreeを持っています。生データのどこかには、取り除かれなかったUTF-8文字があります。 tostringに "encoding = 'UTF-8'"オプションがあるにもかかわらず、ElementTree.writeと.tostringがユニコードで不安定になるようです。ドキュメントはかなり限定されており、私はtostringがUTF-8フレンドリー(ソースを見て)であることさえ確実ではありません。

だから私の質問 - どのnon-ascii文字の全体要素ツリーを取り除くので、このモンスターをディスクに書き込むことができますか(生成に8時間かかりました)?私は今のところそれを漬けた。私はまた、ほとんどのデータにlatin1_to_asciiという関数を使用しました。

def latin1_to_ascii(unicrap):
        """
        This takes a UNICODE string and replaces Latin-1 characters with
        something equivalent in 7-bit ASCII. Anything not converted is deleted.
    #the unicode hammer approach: http://code.activestate.com/recipes/251871-latin1-to-ascii-the-unicode-hammer/
    """
    xlate={0xc0:'A', 0xc1:'A', 0xc2:'A', 0xc3:'A', 0xc4:'A', 0xc5:'A',
            0xc6:'Ae', 0xc7:'C',
            0xc8:'E', 0xc9:'E', 0xca:'E', 0xcb:'E',
            0xcc:'I', 0xcd:'I', 0xce:'I', 0xcf:'I',
            0xd0:'Th', 0xd1:'N',
            0xd2:'O', 0xd3:'O', 0xd4:'O', 0xd5:'O', 0xd6:'O', 0xd8:'O',
            0xd9:'U', 0xda:'U', 0xdb:'U', 0xdc:'U',
            0xdd:'Y', 0xde:'th', 0xdf:'ss',
            0xe0:'a', 0xe1:'a', 0xe2:'a', 0xe3:'a', 0xe4:'a', 0xe5:'a',
            0xe6:'ae', 0xe7:'c',
            0xe8:'e', 0xe9:'e', 0xea:'e', 0xeb:'e',
            0xec:'i', 0xed:'i', 0xee:'i', 0xef:'i',
            0xf0:'th', 0xf1:'n',
            0xf2:'o', 0xf3:'o', 0xf4:'o', 0xf5:'o', 0xf6:'o', 0xf8:'o',
            0xf9:'u', 0xfa:'u', 0xfb:'u', 0xfc:'u',
            0xfd:'y', 0xfe:'th', 0xff:'y',
            0xa1:'!', 0xa2:'{cent}', 0xa3:'{pound}', 0xa4:'{currency}',
            0xa5:'{yen}', 0xa6:'|', 0xa7:'{section}', 0xa8:'{umlaut}',
            0xa9:'{C}', 0xaa:'{^a}', 0xab:'<<', 0xac:'{not}',
            0xad:'-', 0xae:'{R}', 0xaf:'_', 0xb0:'{degrees}',
            0xb1:'{+/-}', 0xb2:'{^2}', 0xb3:'{^3}', 0xb4:"'",
            0xb5:'{micro}', 0xb6:'{paragraph}', 0xb7:'*', 0xb8:'{cedilla}',
            0xb9:'{^1}', 0xba:'{^o}', 0xbb:'>>', 
            0xbc:'{1/4}', 0xbd:'{1/2}', 0xbe:'{3/4}', 0xbf:'?',
            0xd7:'*', 0xf7:'/',0x92:'a'
            }
    r = ''
    for i in unicrap:
            if xlate.has_key(ord(i)):
                    r += xlate[ord(i)]
            elif ord(i) >= 0x80:
                    pass
            else:
                    r += str(i)
    return r

その「原子力オプション」機能は文字列でしか機能せず、要素にデータがあるので、私が見逃したものを取り除くことはできません。

0
8時間? xml.etree.ElementTree または xml.etree.cElementTree を使用していますか?非常に生産的なキーストロークかもしれません...
追加された 著者 John Machin,

4 答え

「UTF-8文字」のように、「元のデータのどこかにUTF-8文字がいくつかありました」と説明する必要があります。なぜそれらを取り除きたいのですか?

また、 "ElementTree.writeと.tostringがユニコードで詰まっているように見える"ことを説明した場合にも役立ちます。質問を編集して完全なエラーメッセージとトレースバックを表示してください。

UnicodeをASCIIに変換するためにその関数を使用したいのはなぜですか?あなたが抱えている問題を単に克服するだけですか?

ElementTreeにUTF-8でエンコードされた str オブジェクトを供給している可能性があります。それをしないでください。 unicode オブジェクトにフィードしてください。

>>> e = et.Element('root')
>>> e.text = u''.join(unichr(i) for i in xrange(0x400, 0x408))
>>> e.text
u'\u0400\u0401\u0402\u0403\u0404\u0405\u0406\u0407'

ASCII出力が必要な場合(7ビット幅のチャネルで通信する場合):

>>> et.tostring(e)
'ЀЁЂЃЄЅІЇ'

UTF-8の動作:

>>> et.tostring(e, 'UTF-8')
"<?xml version='1.0' encoding='UTF-8'?>\n\xd0\x80\xd0\x81\xd0\x82\xd0\x83\xd0\x84\xd0\x85\xd0\x86\xd0\x87"

ElementTree.writeメソッドを使用してファイルを書き込みます。ダブルハンドリングが節約されます。

1
追加された
このpythonスクリプトの出力は、ユニコードではなくascii-Usまたはlatin1のみを受け付ける別の独自のプログラムによって解釈されるXMLファイルです。 ElementTree内のすべての要素とサブ要素、タグ、テールなどを文字列であるかのように変更する便利な方法はありますか?それで私は各文字を読み、ord [128]以下の文字を返すことができます。しかし、まだ提供されているものは見ていない。
追加された 著者 ChewyChunks,

問題は出力ファイルのエンコーディングになる可能性が高いように私には聞こえます。あなたはそれを書く方法をより多くのコードを提供することができますか? ElementTree.write() ElementTree.tostring()がどうやってそれを窒息させるのか分かりません。

0
追加された

私は、ツリーの作成中に入力文字列をUnicodeにデコードして、このプロセスを再度実行します。 8時間は長い時間がかかるかもしれませんが、他人からのメモリ内のパッチ適用のためのポインタを待つのではなく、他のことをすることができます。

作業を続行する前に、コードの動作を確認するためにデータの小さなサブセットをテストしてください。

0
追加された

あなたが私がこのようにして狂っていると思っても、それはうまくいきます。

私はメモ帳++でピクルスファイルを開き、手動ですべての "\ x ??"正規表現で文字を削除して削除しました。 Pythonにピクルをインポートして、ElementTreeをコマンドラインでXMLファイルとして保存しました:

f = open('pulsewire/pulse_cleaned.pickle','rb')

import pickle

data = pickle.load(f)

import xml.etree.ElementTree as ET

bob = ET.ElementTree(data) <-- needed to wrap the Element in Tree first

bob.write("pulsewire/testtree.xml")

0
追加された
それは息をのむほどです。
追加された 著者 John Machin,