Вы уверены, что не хотите, чтобы преобразование было обратимым?Ваша строка ok_expected
означает, что вы не хотите, чтобы существующие символы &
были экранированы, поэтому преобразование будет одним из способов.Приведенный ниже код предполагает, что &
следует экранировать, но просто удалите cgi.escape
, если вы действительно этого не хотите.
В любом случае, я бы объединил ваш оригинальный подход с подстановкой регулярного выражения:кодирование, как и раньше, а затем просто исправить числовые объекты.Таким образом, вы не будете отображать каждый символ с помощью функции getEntity.
#coding=latin-1
import cgi
import re
import htmlentitydefs
def replace_entity(match):
c = int(match.group(1))
name = htmlentitydefs.codepoint2name.get(c, None)
if name:
return "&%s;" % name
return match.group(0)
def convertEntities(s):
s = cgi.escape(s) # Remove if you want ok_expected to pass!
s = s.encode('ascii', 'xmlcharrefreplace')
s = re.sub("&#([0-9]+);", replace_entity, s)
return s
ok = 'ascii: !@#$%^&*()<>'
not_ok = u'extended-ascii: ©®°±¼'
ok_expected = ok
not_ok_expected = u'extended-ascii: ©®°±¼'
ok_2 = convertEntities(ok)
not_ok_2 = convertEntities(not_ok)
if ok_2 == ok_expected:
print 'ascii worked'
else:
print 'ascii failed: "%s"' % ok_2
if not_ok_2 == not_ok_expected:
print 'extended-ascii worked'
else:
print 'extended-ascii failed: "%s"' % not_ok_2