首页 > 深入Python > XML 处理 > Unicode | << >> | ||||
diveintopython.org Python for experienced programmers |
Unicode 是一个系统,用来表示世界上所有不同语言的字符。Python在分析一个XML文档时,所有数据都是以unicode的形式保存在内存中。
一会儿我们就会了解,但首先,先看一些背景知识。
历史记录 在unicode之前,对于每一种语言都存在独立的字符编码系统,每个系统都使用相同的数字(0-255)来表示这种语言的字符。一些语言(象俄语)对于如何表示相同的字符还有几种有冲突的标准;另一些语言(象日语)拥有太多的字符,需要多个字符集。在系统之间进行文档交流是困难的,因为对于一台计算机来说,没有方法可以识别出文档的作者使用了哪种编码模式;计算机看到的只是数字,并且这些数字可以表示不同的东西。接着考虑到试图将这些文档存放到同一个地方(比如在同一个数据库表中);你需要在每段文本的旁边保存字符的编码,并且确保在传递文本的同时将编码也进行传递。接着考虑多语言文档,即在同一文档中使用了不同语言的字符。(比较有代表性的是使用转义符来进行模式切换;扑,我们处于俄语 koi8-r 模式,所以字符 241 表示这个;扑,现在我们处于 Mac 希腊语模式,所以字符 241 表示其它什么。等等。)这些就是unicode被设计出来要解决的问题。
为了解决这些问题,unicode用一个 2 字节数字表示每个字符,从 0 到 65535。[11]每个 2 字节数字表示至少在一种世界语言中使用的一个唯一字符。(在多种语言中都使用的字符具有相同的数字码。)这样就确保每个字符一个数字,并且每个数字一个字符。Unicode数据永远不会表示不明确。
当然,仍然还存在着所有那些遗留的编码系统的情况。例如,7位ASCII码,它可以将英文字符存诸为从0到127的数值。(65是大写字母“A”,97是小写字母“a”,等等。)英语有着非常简单的字母表,所以它可以完全用7位ASCII码来表示。象法语、西班牙语和德语之类的西欧语言都使用叫做ISO-8859-1的编码系统(也叫做“latin-1”),它使用7位ASCII字符表示从0到127的数字,但接着扩展到了128-255的范围来表示象n上带有一个波浪线(241),和u上带有两个点(252)的字符。Unicode使用同7位ASCII码一样的字符表示0到127,同ISO-8859-1一样的字符表示128到255,接着使用剩余的数字,256到65535,扩展到表示其它语言的字符。
在处理unicode数据时,在某些地方你可能需要将数据转换回这些遗留编码系统之一。例如,为了同其它一些计算机系统集成,这些系统期望它的数据使用一种特定的单字节编码模式,或将数据打印输出到一个非unicode识别终端或打印机。或将数据保存到一个明确指定编码模式的XML文档中。
在了解这个注解之后,让我们回到Python上来。
从2.0版本开始,Python在整个语言的基础上已经支持unicode。[12] XML包使用unicode来存储所有分析后的XML数据,但你可以在任何地方使用unicode。
>>> s = u'La Pe\xf1a' >>> print s Traceback (innermost last): File "<interactive input>", line 1, in ? UnicodeError: ASCII encoding error: ordinal not in range(128) >>> print s.encode('latin-1') La Peña
还记得我说过的:一旦需要从一个unicode得出一个正常字符串,Python通常将unicode转换成ASCII吗?嗯,这个缺省编码模式是一个可以定制的选项。
# sitecustomize.py # 这个文件可以放在你的Python搜索路径的任何地方 # 但它通常位于 ${pythondir}/lib/site-packages/ import sys sys.setdefaultencoding('iso-8859-1')
>>> import sys >>> sys.getdefaultencoding() 'iso-8859-1' >>> s = u'La Pe\xf1a' >>> print s La Peña
现在,XML如何?嗯,每个XML文档都有一个指定的编码。再重复一遍,ISO-8859-1是西欧语系中流行的编码。KOI8-R是用于俄语文本的流行编码。如果指定了编码,它会在XML文档的头部(header)。
<?xml version="1.0" encoding="koi8-r"?> <preface> <title>Предисловие</title> </preface>
这是一个从真实的俄语XML文档中进行提取的例子;它是本书 前言 译文的一部分。请注意在头部所指出的编码,koi8-r。 |
|
这些是古代斯拉夫语的字符,就我所知,它们用来拼写俄语单词“前言”。如果你在一个正常文本编辑器中打开这个文件,这些字符非常象乱码,因为它们使用了 koi8-r 编码模式进行编码,但是却以 iso-8859-1 模式进行显示。 |
>>> from xml.dom import minidom >>> xmldoc = minidom.parse('russiansample.xml') >>> title = xmldoc.getElementsByTagName('title')[0].firstChild.data >>> title u'\u041f\u0440\u0435\u0434\u0438\u0441\u043b\u043e\u0432\u0438\u0435' >>> print title Traceback (innermost last): File "<interactive input>", line 1, in ? UnicodeError: ASCII encoding error: ordinal not in range(128) >>> convertedtitle = title.encode('koi8-r') >>> convertedtitle '\xf0\xd2\xc5\xc4\xc9\xd3\xcc\xcf\xd7\xc9\xc5' >>> print convertedtitle Предисловие
概括起来,如果你以前从没看到过unicode,它本身有点唬人,但unicode数据在Python中实际上非常容易处理。如果你的XML文档都是7位ASCII码(如本章中的例子),你差不多永远不会想到unicode。在分析时,Python将把XML文档中的ASCII数据转换成unicode,并且在需要时将它转换回ASCII,而你甚至都没注意到。但如果你需要用其它语言处理数据,Python准备好了。
进一步阅读
脚注
[11] 这一点,很不幸,仍然过分简单了。现在unicode已经扩展用来处理古老的汉字、韩文和日文文本,它们有太多不同的字符,以至于2字节的unicode系统不能全部表示。但Python当前不支持超出范围的编码,并且我不知道是否有正在计划进行解决的项目。对不起,你已经到了我经验的极限了。
[12] Actually, Python has had unicode support since version 1.6, but version 1.6 was a contractual obligation release that nobody likes to talk about, a bastard stepchild of a hippie youth best left forgotten. Even the official Python documentation claims that unicode was “new in version 2.0”. It's a lie, but, like the lies of presidents who say they inhaled but didn't enjoy it, we choose to believe it because we remember our own misspent youths a bit too vividly.
XML 分析 |
1 2 3 4 5 6 7 8 9 |
搜索元素 |