2011-10-27 22 views
0

我已經生成了一個巨大的(50MB)XML ElementTree,並且在原始數據中的某個地方有一些UTF-8字母沒有被去掉。即使在tostring中有一個「encoding ='UTF-8'」選項,ElementTree.write和.tostring似乎也會在unicode上窒息。文檔相當有限,我甚至不確定tostring是UTF-8友好的(查看源代碼)。如何用UTF-8編寫ElementTree

所以我的問題 - 我如何去掉這個非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'?可能是一個非常高效的關鍵筆劃... –

回答

0

我會再次運行該過程,在樹創建期間將輸入字符串解碼爲unicode。八個小時可能會很長時間,但您可以做其他事情,而不是等待指向其他人的內存補丁。

確保在繼續之前測試一小部分數據以確認您的代碼正常工作。

0

聽起來對我來說,這個問題更可能是輸出文件的編碼 - 就像您正在使用的那樣。你能提供更多的代碼來說明你是如何寫出來的嗎?我不明白ElementTree.write()ElementTree.tostring()會如何窒息它。

1

您需要解釋「原始數據中的某處是某些未被剝離的UTF-8字母」 - 例如什麼是「UTF-8字母」,以及爲什麼要剝離它們。

如果你解釋了「ElementTree.write和.tostring似乎在unicode上窒息」的含義,它也會有所幫助。請編輯您的問題以顯示完整的錯誤消息和回溯。

爲什麼你想用這個函數把你的unicode打成ASCII?僅僅是爲了克服你所遇到的問題?

您很可能將str以UTF-8編碼的對象送入ElementTree。不要這樣做。餵養它unicode對象,它只是工作:(?你溝通過7位寬通道)

>>> 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輸出:

>>> 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」;它節省了雙重處理。

+0

此python腳本的輸出是由另一個專有程序解釋的XML文件,該程序只接受ascii-Us或latin1,而不是unicode。那麼是否有任何方便的方法來修改ElementTree中的每個元素和子元素,標籤,尾部等,就好像它是一個字符串?這將允許我只讀每個字母並返回ord [128]或更少的字符。但是還沒有見過類似的東西。 – ChewyChunks

0

好吧,即使你們認爲我瘋了做這種方式,它的工作原理:

我打開鹹菜文件在記事本++和手動發現所有的「\ X?」字符與正則表達式,並刪除它們。然後我進口鹹菜成蟒保存爲使用ElementTree的在命令行的XML文件:

F =開放( 'pulsewire/pulse_cleaned.pickle' 'RB',)

進口泡菜

數據=和pickle.load(F)

進口xml.etree.ElementTree如ET

BOB = ET.ElementTree(數據)< - 需要包裹元件樹第一

bob.write( 「pulsewire/testtree.xml」)

+0

這是驚人的。 –