Python食谱-1.23.Unicode数据编码输出到XML或HTML文件
| 原文作者: | David Goodger, Peter Cogolo |
|---|---|
| 中文翻译: | Tony (digitalsatori) |
问题
要将Uicode文本输出到HTML或是XML应用程序,且只能用较为流行但受限的编码比如:ASCII码,或Latin-1,如何操作?
解决方法
Python 有一个叫 xmlcharrefreplace 的编码出错处理器,它可以将选定编码之外的字符替换为XML数字字符参考(XML numeric characters references):
def encode_for_xml(unicode_data, encoding='ascii'):
return unicode_data.encode(encoding, 'xmlcharrefreplace')
上述的方法也可以用来处理HTML输出,但是我们希望能用HTML的‘符号实体‘(symbolic entity)。这样的话,我们就要自己定义一个函数并将其注册为编码错误处理函数。弄这么个函数其实并不难,因为Python标准库中已经有一个叫 htmlentitydefs 的模块,其包含了所有的HTML的实体定义。
import codecs
from htmlentitydefs import codepoint2name
def html_replace(exc):
if isinstance(exc, (UnicodeEncodeError, UnicodeTranslateError)):
s = [ u'&%s;' % codepoint2name[ord(c)]
for c in exc.object[exc.start:exc.end] ]
return ''.join(s), exc.end
else:
raise TypeError("can't handle %s" % exc._ _name_ _)
codecs.register_error('html_replace', html_replace)
这个错误处理函数注册好之后,我们可以用一个函数来将它封装起来:
def encode_for_html(unicode_data, encoding='ascii'):
return unicode_data.encode(encoding, 'html_replace')
讨论
现在用下面的代码来测试一下(将之与上面的函数放在同一个Python文件中):
if _ _name_ _ == '_ _main_ _':
# demo
data = u'''\
<html>
<head>
</head>
<body>
<p>accented characters:
<ul>
<li>\xe0 (a + grave)
<li>\xe7 (c + cedilla)
<li>\xe9 (e + acute)
</ul>
<p>symbols:
<ul>
<li>\xa3 (British pound)
<li>\u20ac (Euro)
<li>\u221e (infinity)
</ul>
</body></html>
'''
print encode_for_xml(data)
print encode_for_html(data)
运行这个文件,可以看到如下结果:
<li>à (a + grave) <li>ç (c + cedilla) <li>é (e + acute) ... <li>£ (British pound) <li>€ (Euro) <li>∞ (infinity) ... <li>à (a + grave) <li>ç (c + cedilla) <li>é (e + acute) ... <li>£ (British pound) <li>€ (Euro) <li>∞ (infinity)
encode_for_xml 比较通用, encode_for_html 产生的结果的可读性较强。两个函数产生的结果放到浏览器里看是完全一样的。你可以运行以上这个Python文件并将结果重定向到一个html文件,然后用浏览器打开查看。
必须要记得Unicode数据在打印或写入文件前一定要做编码处理。UTF-8是一个不错的字符编码,因为他能处理所有的Unicode字符。但是目前还有很多用户和程序在使用ASCII码或Latin-1。如果Unicode数据中有超出指定编码范围的字符(比如本例中的带重音的字符和所有的符号都无法用ASCII编码,而无限符号(infinity)无法用Latin-1编码),指定的编码无法自己处理这些数据。Python提供了一个称为 xmlcharrefreplace 错误处理函数,它可以将无法编码的字符用XML数字字符参考来替代,比如: ∞ 表示无限符号。在本配方中展示了如何来编写和注册另一个近似的错误处理函数 html_replace ,这个函数主要用于处理HTML输出。 html_replace 将无法编码的字符用更加可读的HTML符号实体来替代,比如用 ∞ 来表示无限符号。 html_replace 不是很通用,因为它并不能处理所有的Unicode字符,而且也不能用于非HTML的应用环境。
上述的错误处理函数对于除XML或HTML以外的输出是没有意义的。比如TeX或其它标记语言并不能识别XML数字字符参考。当然,如果你知道如何为这些标记语言创建相应的符号参考,你就可以用本配方中的方法来创建和注册相应的错误处理函数。
另外,Python标准库中的 codecs 模块提供了一个有效的方法,将Unicode数据编码输出到文件,并根据设定进行错误处理:
outfile = codecs.open('out.html', mode='w', encoding='ascii',
errors='html_replace')
现在我们可以用 outfile.write(unicode_data) 将任意Unicode字符串 unicode_data 输出到指定的文件,编码和错误处理会自动进行。当输出结束后,我们需要调用 outfile.close() 。
参见
Python库参考手册和Python in a Nutshelll中关于 codecs 模块和 htmlentitydefs 的介绍













