如何正确编码来自xml的ISO8859-1的utf8中的字符串

时间:2016-01-26 16:57:52

标签: python xml encoding utf-8

我在python 2.7中使用以下代码来检索包含一些德语变音符号的xmlFile,例如ä,ü,ö,ß:

.....
def getXML(self,url):
    xmlFile=urllib2.urlopen(self.url)
    xmlResponse=xmlFile.read()
    xmlResponse=xmlResponse
    xmlFile.close()
    return xmlResponse
    pass

def makeDict(self, xmlFile):
    data = xmltodict.parse(xmlFile)
    return data

def saveJSON(self, dictionary):
    currentDayData=dictionary['speiseplan']['tag'][1]
    file=open('data.json','w')
    # Write the currentDay as JSON 
    file.write(json.dumps(currentDayData))
    file.close()
    return True
    pass

 # Execute
 url="path/to/xml/"
 App=GetMensaJSON(url)
 xml=GetMensaJSON.getXML(App,url)

 dictionary=GetMensaJSON.makeDict(App,xml)
 GetMensaJSON.saveJSON(App,dictionary)

问题是xml文件在其<xml>标记中声称它是utf-8。但事实并非如此。通过尝试我发现它是iso8859_1 所以我想从utf-8转换到iso8859并回到utf-8来解决冲突。

有没有一种优雅的方法来解决失踪的变音符号?例如,在我的代码中,我而不是ß\u00c3\u009f而不是ü\u00c3\u00bc

我发现了类似的问题,但我无法让它工作How to parse an XML file with encoding declaration in Python?

另外我应该补充一点,我不能影响我获取xml的方式。

可以在代码中找到XML文件链接。

'repr(xmlResponse)'的输出是

 "<?xml version='1.0' encoding='utf-8'?>\n<speiseplan>\n<tag timestamp='1453676400'>\n<item language='de'>\n<category>Stammessen</category>\n<title>Gem\xc3\x83\xc2\xbcsebr\xc3\x83\xc2\xbche mit Backerbsen (25,28,31,33,34), paniertes H\xc3\x83\xc2\xa4hnchenbrustschnitzel (25) mit Paprikasauce (33,34), Pommes frites und Gem\xc3\x83\xc2\xbcse

1 个答案:

答案 0 :(得分:2)

您正在尝试编码已编码的数据urllib2.urlopen()只能返回一个字节字符串,而不是unicode,所以编码没什么意义。

相反,Python会在这里发挥作用;如果你坚持编码字节,那么它会先解码那些unicode数据 。并且它将使用默认的编解码器。

最重要的是,XML文档本身负责记录应该使用哪种编解码器进行解码。默认编解码器是UTF-8,不要自己手动重新编码数据,将其留给XML解析器。

如果您的XML文档中有Mojibake data,解决此问题的最佳方法是在解析后执行此操作。我建议ftfy包为您执行此操作。

可以手动修复&#39;编码首先解码为UTF-8,然后再次编码为Latin-1:

xmlResponse = xmlFile.read().decode('utf-8').encode('latin-1')

然而,这假设您的数据已被严重解码为Latin-1开头;这并不总是一个安全的假设。例如,如果它被解码为Windows CP 1252,那么恢复数据的最佳方法仍然是使用ftfy

您可以尝试在解析之前使用ftfy 作为XML,但这取决于文档没有使用文本和属性内容之外的任何非ASCII元素:

xmlResponse = ftfy.fix_text(
    xmlFile.read().decode('utf-8'),
    fix_entities=False, uncurl_quotes=False, fix_latin_ligatures=False).encode('utf-8')