| You are here: Inicio > Inmersión en Python > Procesamiento de XML > Unicode | << >> | ||||
Inmersión en PythonPython de novato a experto |
|||||
Unicode es un sistema para representar caracteres de todos los diferentes idiomas en el mundo. Cuando Python analiza un documento XML, todos los datos se almacenan en memoria como unicode.
Llegaremos a eso en un momento, pero antes, unos antecedentes.
Nota histórica. Antes de unicode, había diferentes sistemas de codificación de caracteres para cada idioma, cada uno usando los mismos números (0-255) para representar los caracteres de ese lenguaje. Algunos (como el ruso) tienen varios estándares incompatibles que dicen cómo representar los mismos caracteres; otros idiomas (como el japonés) tienen tantos caracteres que precisan más de un byte. Intercambiar documentos entre estos sistemas era difícil porque no había manera de que un computador supiera con certeza qué esquema de codificación de caracteres había usado el autor del documento; el computador sólo veía números, y los números pueden significar muchas cosas. Piense entonces en almacenar estos documentos en el mismo sitio (como en una tabla de una base de datos); necesitaría almacenar el tipo de codificación junto con cada texto, y asegurarse de adjuntarlo con el texto cada vez que accediese a él. Ahora imagine documentos multilingües, con caracteres de varios idiomas en el mismo document. (Habitualmente utilizaban códigos de escape para cambiar de modos; ¡puf!, está en modo ruso koi8-r así que el carácter 241 significa esto; ¡puf!, ahora está en modo Mac Greek, así que el carácter 241 significa otra cosa. Y así con todo). Para resolver estos problemas se diseñó unicode.
Para resolver estos problemas, unicode representa cada carácter como un número de 2 bytes, de 0 a 65535.[10] Cada número de 2 bytes representa un único carácter utilizado en al menos un idioma del mundo (los caracteres que se usan en más de un idioma tienen el mismo código numérico). Hay exactamente 1 número por carácter, y exactamente 1 carácter por número. Los datos de unicode nunca son ambiguos.
Por supuesto, sigue estando el problema de todos esos sistemas de codificación anticuados. Por ejemplo, el ASCII de 7 bits que almacena los caracteres ingleses como números del 0 al 127 (65 es la “A”, mayúscula, 97 es la “a” minúscula, etc.). El inglés tiene un alfabeto sencillo, así que se puede expresar en ASCII de 7 bits. Los idiomas europeos occidentales como el francés, español y alemán usan todos un sistema llamado ISO-8859-1 (también conocido como “latin-1”), que usa los caracteres del ASCII de 7 bits del 0 al 127, pero lo extiende en el rango 128-255 para tener caracteres como n-con-una-tilde-sobre-ella (241) y u-con-dos-puntitos-sobre-ella (252). Y unicode usa los mismos caracteres que el ASCII de 7 bits para los números del 0 al 127, y los mismos caracteres que ISO-8859-1 del 128 al 255, y de ahí en adelante se extiende para otros lenguajes que usan el resto de los números, del 256 al 65535.
Puede que en algún momento al tratar con datos unicode tengamos la necesidad de convertirlos en alguno de estos otros sistemas anticuados. Por ejemplo, por necesidad de integración con algún sistema computador que espera que sus datos estén en un esquema específico de 1 byte, o para imprimirlo en alguna terminal o impresora que desconozca unicode. O para almacenarlo en un documento XML que especifique explícitamente la codificación de los caracteres.
Y dicho esto, volvamos a Python.
Python trabaja con unicode desde la versión 2.0 del lenguaje. El paquete XML utiliza unicode para almacenar todos los datos XML, pero puede usar unicode en cualquier parte.
>>> s = u'Dive in'>>> s u'Dive in' >>> print s
Dive in
>>> 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
| La verdadera ventaja de unicode, por supuesto, es su capacidad de almacenar caracteres que no son ASCII, como la “ñ” española. El carácter unicode para la ñ es 0xf1 en hexadecimal (241 en decimal), que se puede escribir así: \xf1[11] | |
| ¿Recuerda que dije que la función print intenta convertir una cadena unicode en ASCII para poder imprimirla? Bien, eso no funcionará aquí, porque la cadena unicode contiene caracteres que no son de ASCII, así que Python produce un error UnicodeError. | |
| Aquí es donde entra la conversión-de-unicode-a-otros-esquemas-de-codificación. s es una cadena unicode, pero print sólo puede imprimir cadenas normales. Para resolver este problema, llamamos al método encode, disponible en cada cadena unicode, para convertir la cadena unicode en una cadena normal en el esquema dado, que le pasamos como parámetro. En este caso usamos latin-1 (también conocido como iso-8859-1), que incluye la ñ (mientras que el código ASCII no, ya que sólo incluye caracteres numerados del 0 al 127). |
¿Recuerda cuando le dije que Python normalmente convierte el unicode a ASCII cuando necesita hacer una cadena normal partiendo de una unicode? Bien, este esquema por omisión es una opción que puede modificar.
# 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
Si va a almacenar caracteres que no sean ASCII dentro de código de Python, necesitará especificar la codificación en cada fichero .py poniendo una declaración de codificación al inicio de cada uno. Esta declaración indica que el fichero .py contiene UTF-8:
#!/usr/bin/env python # -*- coding: UTF-8 -*-
Ahora, ¿qué pasa con XML? Bueno, cada documento XML está en una codificación específica. ISO-8859-1 es una codificación popular para los datos en idiomas europeos occidentales. KOI8-R es habitual en textos rusos. Si se especifica, la codificación estará en la cabecera del documento 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
Предисловие
Para resumir, unicode en sí es un poco intimidante si nunca lo ha visto antes, pero los datos en unicode son muy fáciles de manejar con Python. Si sus documentos XML están todos en ASCII de 7 bits (como los ejemplos de este capítulo), nunca tendrá que pensar sobre unicode, literalmente. Python convertirá los datos ASCII de los documentos XML en unicode mientras lo analiza, y los autoconvertirá a ASCII cuando sea necesario, y ni siquiera lo notará. Pero si necesita tratar con otros idiomas, Python está preparado.
[10] Tristemente, esto no es más que una simplificación extrema. Unicode ha sido extendido para poder tratar textos clásicos chinos, coreanos y japoneses, que tienen tantos caracteres diferentes que el sistema unicode de 2 bytes no podía representarlos todos. Pero Python no soporta eso de serie, y no sé si hay algún proyecto en marcha para añadirlo. Hemos llegado a los límites de mi conocimiento, lo siento.
[11] N. del T.: Dado que está leyendo este texto en español, es bastante probable que también cuente con una ñ en el teclado y pueda escribirla sin recurrir al hexadecimal, pero aún así he decidido mantener el ejemplo tal cual está en el original, ya que ilustra el concepto.
<< Análisis de XML |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
Búsqueda de elementos >> |