Как написать ElementTree с убранным UTF-8 - PullRequest
0 голосов
/ 28 октября 2011

У меня есть гигантское (50 МБ) XML ElementTree, которое я сгенерировал, и где-то в исходных данных были некоторые буквы UTF-8, которые не были удалены. ElementTree.write и .tostring, кажется, душат юникод, хотя в tostring есть опция "encoding = 'UTF-8'". Документы довольно ограничены, и я даже не уверен, что tostring подходит для UTF-8 (глядя на источник).

Итак, мой вопрос - как мне удалить целое дерево элементов из любых не-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

эта функция «ядерной опции» работает только со строками, и теперь, когда у меня есть данные в элементе, я не могу избавиться от того, что пропустил.

Ответы [ 4 ]

1 голос
/ 28 октября 2011

Вам нужно объяснить, что «где-то в исходных данных были какие-то буквы UTF-8, которые не были удалены» - например, что такое «буква UTF-8», и почему вы хотите удалить их.

Было бы также полезно, если бы вы объяснили, что означают "ElementTree.write и .tostring, кажется, душат юникод". Пожалуйста, отредактируйте свой вопрос, чтобы показать полное сообщение об ошибке и трассировку.

Почему вы хотите использовать эту функцию, чтобы использовать Unicode в ASCII? Это просто для преодоления проблем, с которыми вы сталкиваетесь?

Возможно, что вы подаете str объекты, закодированные в UTF-8, в ElementTree. Не делай этого. Накормите это 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)
'<root>&#1024;&#1025;&#1026;&#1027;&#1028;&#1029;&#1030;&#1031;</root>'

UTF-8 работает:

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

Вы должны использовать ElementTree.write метод для записи вашего файла, вместо того, чтобы использовать 'tostring'; экономит двойную обработку.

0 голосов
/ 29 октября 2011

Хорошо, даже если вы, ребята, думаете, что я сумасшедший, что я так поступаю, это работает:

Я открыл файл pickle в Notepad ++ и вручную нашел все "\ x ??"символы с регулярным выражением, и удалил их.Затем я импортировал рассол в python для сохранения в виде XML-файла, используя ElementTree в командной строке:

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

import pickle

data = pickle.load (f)

import xml.etree.ElementTree как ET

bob = ET.ElementTree (данные) <- необходимо сначала обернуть элемент в дереве </p>

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

0 голосов
/ 28 октября 2011

мне кажется, что проблема, скорее всего, заключается в кодировке выходного файла, с которой вы работаете.Не могли бы вы предоставить больше кода, как вы пытаетесь записать его?Я не понимаю, как ElementTree.write() и ElementTree.tostring() могут задыхаться от этого.

0 голосов
/ 28 октября 2011

Я бы запустил процесс снова, расшифровав входные строки в unicode во время создания дерева. Восемь часов могут занять много времени, но вы можете заниматься другими делами, вместо того, чтобы ждать указателей на исправления в памяти от других.

Обязательно протестируйте небольшой набор данных, чтобы убедиться, что код работает, прежде чем продолжить.

...