2012-04-06 15 views
9

Tôi đang cố gắng để viết một tập tin xml với utf-8 mã hóa dữ liệu sử dụng ElementTree như thế này:Viết xml tập tin utf-8 với utf 8-dữ liệu với ElementTree

#!/usr/bin/python                  
# -*- coding: utf-8 -*-                 

import xml.etree.ElementTree as ET 
import codecs 

testtag = ET.Element('unicodetag') 
testtag.text = u'Töreboda' #The o is really ö (o with two dots over). No idea why SO dont display this 
expfile = codecs.open('testunicode.xml',"w","utf-8-sig") 
ET.ElementTree(testtag).write(expfile,encoding="UTF-8",xml_declaration=True) 
expfile.close() 

này thổi lên với lỗi

Traceback (most recent call last): 
    File "unicodetest.py", line 10, in <module> 
    ET.ElementTree(testtag).write(expfile,encoding="UTF-8",xml_declaration=True) 
    File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 815, in write 
    serialize(write, self._root, encoding, qnames, namespaces)  
    File "/usr/lib/python2.7/xml/etree/ElementTree.py", line 932, in _serialize_xml 
    write(_escape_cdata(text, encoding)) 
    File "/usr/lib/python2.7/codecs.py", line 691, in write 
    return self.writer.write(data) 
    File "/usr/lib/python2.7/codecs.py", line 351, in write 
    data, consumed = self.encode(object, self.errors) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128) 

Sử dụng mã hóa "us-ascii" thay vì hoạt động tốt, nhưng không giữ lại các ký tự unicode trong dữ liệu. Điều gì đang xảy ra?

Trả lời

17

codecs.open mong muốn chuỗi Unicode được ghi vào đối tượng tệp và nó sẽ xử lý mã hóa thành UTF-8. Phần tử write của ElementTree mã hóa chuỗi Unicode thành chuỗi byte UTF-8 trước khi gửi chúng đến đối tượng tệp. Vì đối tượng tệp muốn các chuỗi Unicode, nó sẽ cắt xâu chuỗi byte thành Unicode bằng cách sử dụng codec mặc định ascii và gây ra UnicodeDecodeError.

Chỉ cần làm điều này:

#expfile = codecs.open('testunicode.xml',"w","utf-8-sig") 
ET.ElementTree(testtag).write('testunicode.xml',encoding="UTF-8",xml_declaration=True) 
#expfile.close() 
+2

+1. Chỉ cần làm rõ điều này: vấn đề là bạn đang cố gắng mã hóa unicode-> utf-8 hai lần: ElementTree thực hiện một lần, và sau đó luồng hỗ trợ codec cố gắng thực hiện lại. Nhưng lần truyền thứ hai này bị nhầm lẫn vì đầu vào của nó đã được mã hóa (nó dự kiến ​​một chuỗi unicode, nhưng thay vào đó sẽ nhận được chuỗi byte được mã hóa utf-8). –

+0

Ở đây tôi đi khập khiễng nghĩ rằng tôi đang giúp đỡ bằng cách cung cấp một tập tin unicode ... Tôi có thể nói rằng tôi yêu stackoverflow? Một câu trả lời hoàn hảo trong vòng 3 giờ! Marks xây dựng là giải thích rất nhiều quá. – c0m4

+1

Tôi đã xử lý dữ liệu utf-8 và nhận được một lỗi tương tự trong ElementTree._serialize_text() hoặc _serialize_xml() khi cố ghi vào tệp xml. Tôi đã có thể giải quyết nó bằng cách chuyển đổi chuỗi của tôi thành unicode bằng cách sử dụng myString.decode ('utf-8') trước khi thêm chúng vào đối tượng ET.Element của tôi. Có vẻ như ET.ElementTree.write() không hài lòng với các mã hóa chuỗi khác. – drevicko

Các vấn đề liên quan