Как конвертировать расширенный ASCII в имена объектов HTML в Python? - PullRequest
3 голосов
/ 22 июля 2010

В настоящее время я делаю это, чтобы заменить символы расширенного ascii их эквивалентными числами HTML-сущности:

s.encode('ascii', 'xmlcharrefreplace')

То, что я хотел бы сделать, - это преобразовать его в эквивалент HTML-сущности-имени (т.е. © вместо ©). Эта небольшая программа ниже показывает, что я пытаюсь сделать, но не могу. Есть ли способ сделать это, кроме поиска / замены?

#coding=latin-1

def convertEntities(s):
    return s.encode('ascii', 'xmlcharrefreplace')

ok = 'ascii: !@#$%^&*()<>'
not_ok = u'extended-ascii: ©®°±¼'

ok_expected = ok
not_ok_expected = u'extended-ascii: &copy;&reg;&deg;&plusmn;&frac14;'

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

Ответы [ 5 ]

2 голосов
/ 23 июля 2010

Является ли htmlentitydefs тем, что вы хотите?

import htmlentitydefs
htmlentitydefs.codepoint2name.get(ord(c),c)
2 голосов
/ 23 июля 2010

edit

Другие упоминали htmlentitydefs, о котором я никогда не знал.Это будет работать с моим кодом следующим образом:

from htmlentitydefs import entitydefs as symbols

for tag, val in symbols.iteritems():
   mystr = mystr.replace("&{0};".format(tag), val)

И это должно сработать.

1 голос
/ 23 июля 2010

Обновление Это решение, с которым я собираюсь поработать, с небольшим исправлением, чтобы проверить, что entitydefs содержит отображение для символа, который у нас есть.

def convertEntities(s):
    return ''.join([getEntity(c) for c in s])

def getEntity(c):
    ord_c = ord(c)
    if ord_c > 127 and ord_c in htmlentitydefs.codepoint2name:
        return "&%s;" % htmlentitydefs.codepoint2name[ord_c]
    return c
1 голос
/ 23 июля 2010

Я не уверен, как напрямую, но я думаю, что модуль htmlentitydefs будет полезен.Пример можно найти здесь .

0 голосов
/ 23 июля 2010

Вы уверены, что не хотите, чтобы преобразование было обратимым?Ваша строка 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: &copy;&reg;&deg;&plusmn;&frac14;'

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
...