Reemplace las referencias de caracteres numéricos en documentos XML usando Python

Estoy teniendo problemas con el siguiente problema: tengo una cadena XML que contiene la siguiente etiqueta y quiero convertirla, usando cElementTree, en un documento XML válido:

#55296;#57136;#55296;#57149;#55296;#57139;#55296;#57136;#55296;#57151;#55296; #57154;#55296;#57136; 

pero cada signo # está precedido por un signo & y, por lo tanto, la salida se ve así:

Esta es una cadena Unicode y la encoding es UTF-8. Quiero descartar estas referencias de caracteres numéricos porque no son XML legales en un documento XML válido (ver error del analizador usando el módulo Perl XML :: DOM, “referencia a número de caracteres no válido” )

He intentado diferentes expresiones regulares para hacer coincidir estas referencias numéricas de caracteres. Por ejemplo, he intentado la siguiente expresión regular (Python):

 RE_NUMERIC_CHARACTER = re.compile('&#[\d{1,5}]+;') 

Esto funciona en una sesión regular de Python, pero tan pronto como uso la misma expresión regular en mi código, entonces no funciona, probablemente porque esos caracteres numéricos han sido interpretados (y se muestran como cuadros o signos de interrogación).

También he probado la función unescape de http://effbot.org/zone/re-sub.htm pero eso tampoco funciona.

Por lo tanto: ¿cómo puedo hacer coincidir, usando una expresión regular en Python, estas referencias numéricas de caracteres y crear un documento XML válido?

Eurgh Tienes sustitutos (unidades de código UTF-16 en el rango D800-DFFF), que algún tonto ha codificado incorrectamente de forma individual en lugar de usar un par de unidades de código para un solo carácter. Sería ideal reemplazar este lío con el aspecto que debería tener:

 𐌰𐌽𐌳𐌰𐌿𐍂𐌰 

O, como válido, en caracteres literales (si tienes una fuente que puede mostrar el alfabeto gótico):

 𐌰𐌽𐌳𐌰𐌿𐍂𐌰 

Por lo general, lo mejor sería realizar operaciones de reemplazo como esta en los nodos de texto analizado, para evitar desordenar las secuencias sin referencia de caracteres en otros lugares como comentarios o PI. Sin embargo, por supuesto, eso no es posible en este caso, ya que esto no es realmente XML en absoluto. Podría intentar arreglarlo con una expresión regular bruta, aunque sería mejor averiguar de dónde proviene la entrada no válida y patear a la persona responsable hasta que la arregle.

 >>> def lenient_deccharref(m): ... return unichr(int(m.group(1))) ... >>> tag= '��������������' >>> re.sub('&#(\d+);', lenient_deccharref, tag).encode('utf-8') '\xf0\x90\x8c\xb0\xf0\x90\x8c\xbd\xf0\x90\x8c\xb3\xf0\x90\x8c\xb0\xf0\x90\x8c\xbf\xf0\x90\x8d\x82\xf0\x90\x8c\xb0' 

Esta es la encoding UTF-8 correcta de 𐌰𐌽𐌳𐌰𐌿𐍂𐌰 . El códec utf-8 permite codificar una secuencia de sustitutos para corregir UTF-8 incluso en una plataforma amplia de Unicode donde los sustitutos no deberían haber aparecido en la cadena en primer lugar.

 >>> _.decode('utf-8') u'\U00010330\U0001033d\U00010333\U00010330\U0001033f\U00010342\U00010330'