【问题标题】:How to write an ElementTree with UTF-8 stripped out如何编写去掉 UTF-8 的 ElementTree
【发布时间】:2023-03-24 22:13:01
【问题描述】:

我生成了一个巨大的 (50MB) XML ElementTree,在原始数据的某处有一些 UTF-8 字母没有被删除。即使 tostring 中有一个“encoding='UTF-8'”选项,ElementTree.write 和 .tostring 似乎也会在 unicode 上窒息。文档相当有限,我什至不确定 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

“核选项”功能仅适用于字符串,现在我在元素中有数据,我似乎无法删除我错过的内容。

【问题讨论】:

  • 8 小时?您使用的是xml.etree.ElementTree 还是xml.etree.cElementTree?可能是一个非常有成效的击键......

标签: python unicode utf-8 tostring elementtree


【解决方案1】:

您需要解释“原始数据中的某处有一些未删除的 UTF-8 字母”——比如什么是“UTF-8 字母”,以及为什么要删除它们。

如果您解释“ElementTree.write 和 .tostring 似乎在 unicode 上窒息”的含义,这也会有所帮助。请编辑您的问题以显示完整的错误消息和回溯。

为什么要使用该函数将 unicode 转换为 ASCII?仅仅是为了克服你遇到的问题吗?

您很可能正在将 UTF-8 编码的 str 对象提供给 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 method 来编写您的文件,而不是使用'tostring';它节省了双重处理。

【讨论】:

  • 这个 python 脚本的输出是一个由另一个专有程序解释的 XML 文件,它只接受 ascii-Us 或 latin1,而不是 unicode。那么是否有任何方便的方法可以修改 ElementTree 中的每个元素和子元素、标记、尾部等,就好像它是一个字符串一样?这将允许我阅读每个字母并返回具有 ord[128] 或更少的字符。但还没有看到提供类似的东西。
【解决方案2】:

我会再次运行该过程,在树创建期间将输入字符串解码为 un​​icode。八小时可能很长,但您可以做其他事情,而不是等待其他人在内存中修补的指针。

在继续之前,请务必对一小部分数据进行测试,以确认您的代码可以正常工作。

【讨论】:

    【解决方案3】:

    在我看来,问题更可能是您正在使用的输出文件的编码。您能否提供更多代码来说明您如何尝试将其写出来?我看不出ElementTree.write()ElementTree.tostring() 怎么会窒息。

    【讨论】:

      【解决方案4】:

      好吧,即使你们认为我这样做很疯狂,它仍然有效:

      我在 Notepad++ 中打开了 pickle 文件并手动找到了所有的 "\x??"带有正则表达式的字符,并删除它们。然后我将泡菜导入 python 以在命令行使用 ElementTree 保存为 XML 文件:

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

      进口泡菜

      数据 = pickle.load(f)

      将 xml.etree.ElementTree 导入为 ET

      bob = ET.ElementTree(data)

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

      【讨论】:

        猜你喜欢
        • 2012-04-20
        • 1970-01-01
        • 2020-06-30
        • 2015-01-27
        • 2013-11-19
        • 2010-11-03
        相关资源
        最近更新 更多