lax文件的编码问题

解析blackberry的设备应用文件alx,格式是xml的,但文件没有标明编码,也没有<?xml version="1.0" ?>类似的标注。文件的编码,尤其是要读取未知编码的文件,是比较痛苦的事。在linux下,可以通过file命令来获取文件的编码

file -i BlackBerry.alx

会得到类似下边的结果,可以看出其编码iso-8859-1

BlackBerry.alx: text/plain; charset=iso-8859-1

详细了解file命令查看这里

可以看到alx文件的编码是iso-8859-1

它的一个别名是Latin-1

# 读取文件内容,并转为utf-8编码,
fp = codecs.open(filepath, 'r', 'latin-1')
content = fp.read().encode('utf-8', errors="xmlcharrefreplace")
fp.close()

# 之后用minidom来解析改文件
xmldoc = minidom.parseString(content)
# ...deal with xmldoc

#保存修改后的文件
xmlstr = xmldoc.toxml() #默认是unicode字符串,也可以指定编码
# 转码,其中包含中文和其他一些字符是无法转为latin-1编码的,一定要指定errors的处理方式
content = xmlstr.encode('latin-1', errors="xmlcharrefreplace")
#errors的详细处理信息 http://docs.python.org/library/codecs.html

fp = open(filename, "w")
fp.write(content)
fp.close()

如果只到此,用diff工具查看原文件和修改过后的文件,会发现很多不同,而且修改后的文件无法被正确读取,

认真查看这些不同处,会发现,其中一大部分是由于xml的标签的属性间位置的改变,这个不影响读取

余下的不同处,会发现是类似&#x6838;和&#26680;之间的不同,前者用十六进制表示unicode编码,后者用十进制表示

按理这个应该是一样的,但使用后者,原程序就是无法识别,所以后者必须转换成前者

通过正则表达式来替换

def hexrepl(match):
value = int(match.group(1))
hex_str = str(hex(value))[2:]
count = len(hex_str)
for _ in xrange(4-count):
hex_str = "0%s"% hex_str
return "&#x%s;"% hex_str

p = re.compile(r'&#(\d+);')
content = p.sub(hexrepl, content)



posted @ 2011-10-09 23:42  kebo  阅读(508)  评论(0编辑  收藏  举报