您在这里:首页 > 深入 Python > XML 处理 > Unicode | << >> | ||||
深入 Python从 Python 新手到专家 |
Unicode 是一种用于表示世界上所有不同语言字符的系统。当 Python 解析 XML 文档时,所有数据都以 Unicode 格式存储在内存中。
我们稍后会详细讨论,但首先,让我们先了解一些背景知识。
**历史注释。** 在 Unicode 出现之前,每种语言都有各自独立的字符编码系统,每个系统都使用相同的数字(0-255)来表示该语言的字符。有些语言(如俄语)在如何表示相同的字符方面存在多种相互冲突的标准;而另一些语言(如日语)则拥有非常多的字符,以至于需要使用多字节字符集。在不同系统之间交换文档非常困难,因为计算机无法确定文档作者使用了哪种字符编码方案;计算机只能看到数字,而这些数字可能代表不同的含义。然后,想象一下尝试将这些文档存储在同一个地方(例如同一个数据库表中);您需要将字符编码与每段文本一起存储,并在传递文本时确保一并传递编码信息。再想象一下多语言文档,同一个文档中包含来自多种语言的字符。(它们通常使用转义码来切换模式;例如,您现在处于俄语 koi8-r 模式,因此字符 241 表示这个意思;然后,您切换到 Mac 希腊语模式,字符 241 就表示其他意思。以此类推。)Unicode 的设计就是为了解决这些问题。
为了解决这些问题,Unicode 使用 0 到 65535 之间的 2 字节数字来表示每个字符。[5] 每个 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 数据时,您有时可能需要将数据转换回其中一种遗留编码系统。例如,为了与其他期望使用特定 1 字节编码方案的计算机系统集成,或者为了将其打印到不支持 Unicode 的终端或打印机上。或者将其存储在明确指定编码方案的 XML 文档中。
说到这里,让我们回到 Python。
从 2.0 版本开始,Python 就开始在整个语言中支持 Unicode。 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
还记得我说过,每当 Python 需要从 Unicode 字符串生成常规字符串时,它通常会将 Unicode 转换为 ASCII 吗?嗯,这个默认编码方案是一个您可以自定义的选项。
# sitecustomize.py# this file can be anywhere in your Python path, # but it usually goes in ${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
如果您要在 Python 代码中存储非 ASCII 字符串,则需要通过在每个文件的顶部放置一个编码声明来指定每个 .py 文件的编码。此声明将 .py 文件定义为 UTF-8
#!/usr/bin/env python # -*- coding: UTF-8 -*-
现在,XML 呢?嗯,每个 XML 文档都使用特定的编码。同样,ISO-8859-1 是一种流行的西欧语言数据编码。KOI8-R 在俄语文本中很流行。如果指定了编码,则编码位于 XML 文档的标头中。
<?xml version="1.0" encoding="koi8-r"?><preface> <title>Предисловие</title>
</preface>
>>> 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,它本身可能会有点吓人,但在 Python 中处理 Unicode 数据实际上非常容易。如果您的 XML 文档都是 7 位 ASCII(如本章中的示例),您实际上永远不会想到 Unicode。Python 会在解析时将 XML 文档中的 ASCII 数据转换为 Unicode,并在必要时自动将其强制转换回 ASCII,而您甚至不会注意到。但如果您需要用其他语言处理它,Python 也已准备就绪。
[5] 遗憾的是,这仍然过于简单了。Unicode 现在已经扩展到可以处理古代汉语、韩语和日语文本,这些文本有太多不同的字符,以至于 2 字节的 Unicode 系统无法全部表示。但是 Python 目前不支持开箱即用的功能,而且我不知道是否有正在进行的项目来添加它。很抱歉,这已经超出了我的专业知识范围。
<< 解析 XML |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
搜索元素 >> |