2012-01-03 35 views
6

Dưới đây là một lỗi phổ biến khi giao dịch với UTF-8 - 'thẻ không hợp lệ'Python UTF-8 XML phân tích cú pháp (bọt): Loại bỏ 'dấu hiệu không hợp lệ'

Trong ví dụ của tôi, Nó xuất phát từ đối phó với một nhà cung cấp dịch vụ SOAP mà không có sự tôn trọng đối với các ký tự unicode, chỉ cần cắt bỏ các giá trị đến 100 byte và bỏ qua rằng byte 100'th có thể ở giữa một nhân vật đa byte: ví dụ:

<name xsi:type="xsd:string">浙江家庭教会五十人遭驱散及抓打 圣诞节聚会被断电及抢走物品(图、视频\xef\xbc</name> 

hai byte cuối cùng là gì còn lại của một ký tự unicode 3 byte, sau khi con dao cắt ngắn giả định rằng thế giới sử dụng các ký tự 1 byte. Điểm dừng tiếp theo, trình phân tích cú pháp sax và:

xml.sax._exceptions.SAXParseException: <unknown>:1:2392: not well-formed (invalid token) 

Tôi không quan tâm đến nhân vật này nữa. Nó phải được loại bỏ khỏi tài liệu và cho phép trình phân tích cú pháp sax hoạt động.

Trả lời XML hợp lệ ở mọi khía cạnh khác ngoại trừ các giá trị này.

Câu hỏi: Làm thế nào để bạn loại bỏ ký tự này mà không phân tích cú pháp toàn bộ tài liệu và tái phát minh mã hóa UTF-8 để kiểm tra từng byte?

Sử dụng: Python + bọt

Trả lời

17

Hóa ra, bọt thấy xml as type 'string' (không unicode) do đó, những giá trị được mã hóa.

1) Các LỌC:

badXML = "your bad utf-8 xml here" #(type <str>) 

#Turn it into a python unicode string - ignore errors, kick out bad unicode 
decoded = badXML.decode('utf-8', errors='ignore') #(type <unicode>) 

#turn it back into a string, using utf-8 encoding. 
goodXML = decoded.encode('utf-8') #(type <str>) 

2) bọt: xem https://fedorahosted.org/suds/wiki/Documentation#MessagePlugin

from suds.plugin import MessagePlugin 
class UnicodeFilter(MessagePlugin): 
    def received(self, context): 
     decoded = context.reply.decode('utf-8', errors='ignore') 
     reencoded = decoded.encode('utf-8') 
     context.reply = reencoded 

from suds.client import Client 
client = Client(WSDL_url, plugins=[UnicodeFilter()]) 

Hope this helps một ai đó.


Lưu ý: Nhờ John Machin!

Xem: Why is python decode replacing more than the invalid bytes from an encoded string?

Python issue8271 về errors='ignore' có thể nhận được theo cách của bạn ở đây. Nếu không có lỗi này cố định trong python, 'bỏ ​​qua' sẽ tiêu thụ vài byte tiếp theo để đáp ứng độ dài

trong giải mã một chuỗi không hợp lệ UTF-8 byte, chỉ có
khởi byte và byte tiếp (s) bây giờ được coi là không hợp lệ, thay vì số lượng các byte theo quy định của byte đầu

Issue đã được cố định trong:
Python 2.6.6 rc1
Python 2.7.1 rc1 (và tất cả các phiên bản tương lai của 2,7)
Python 3.1.3 rc1 (và tất cả bản phát hành tương lai của 3.x)

Python 2.5 trở xuống sẽ chứa vấn đề này.

Trong ví dụ trên, "\xef\xbc</name".decode('utf-8', errors='ignore') nên
trả về "</name", nhưng trong phiên bản 'bugged' của python, nó trả về "/name".

Bốn bit đầu tiên (0xe) mô tả một nhân vật 3-byte UTF, vì vậy các byte 0xef, 0xbc, và sau đó (sai lầm) 0x3c ('<') được tiêu thụ.

0x3c không phải là byte tiếp tục hợp lệ tạo ký tự UTF 3 byte không hợp lệ ở vị trí đầu tiên.

phiên bản cố định của python chỉ loại bỏ các byte đầu tiên và chỉ có giá trị tiếp tục byte, để lại 0x3c unconsumed

+1

vâng, tôi vừa trả lời câu hỏi của riêng mình. : P – FlipMcF

+0

Tốt cho bạn. +1. – sberry

+0

Huy hiệu Self Learner kiếm được ... (đó là điểm, thực sự!) Cảm ơn bạn. – FlipMcF

0

@ FlipMcF là câu trả lời đúng - Tôi chỉ đăng bộ lọc của tôi cho giải pháp của mình, vì một bản gốc đã không làm việc cho tôi (tôi đã có một số ký tự biểu tượng cảm xúc trong XML của tôi, được mã hóa chính xác trong UTF-8, nhưng chúng vẫn bị lỗi phân tích cú pháp XML):

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