Этот вопрос похож на Удалить html-символьные объекты в строке вопрос, заданный ранее при переполнении стека. Однако принятый ответ не затрагивает проблему именованных сущностей HTML, например, ä
для символа ä
; Поэтому он не может скрыть весь HTML.
У меня есть наследствоHTML, который использует именованные сущности HTML для не-ASCII символов.То есть ö
вместо ö
, ä
вместо ä
и так далее. Полный список всех именованных сущностей HTML доступен в Википедии.
Я бы хотел быстро и эффективно вывести эти HTML-сущности в их символьные эквиваленты.
У меня есть код для этого в Python 3 с использованием регулярных выражений:
import re
import html.entities
s = re.sub(r'&(\w+?);', lambda m: chr(html.entities.name2codepoint[m.group(1)]), s)
Однако регулярные выражения не кажутся очень популярными, быстрыми или простыми в использовании на Haskell.
Text.HTML.TagSoup.Entity
(tagsoup) имеет полезную таблицу и функции для отображения именованных объектов в кодовые точки tpo.Используя этот пакет и пакет regex-tdfa, я создал чрезвычайно медленный эквивалент в Haskell:
{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString.Lazy.Char8 as L
import Data.ByteString.Lazy.UTF8 as UTF8
import Text.HTML.TagSoup.Entity (lookupEntity)
import Text.Regex.TDFA ((=~~))
unescapeEntites :: L.ByteString -> L.ByteString
unescapeEntites = regexReplaceBy "&#?[[:alnum:]]+;" $ lookupMatch
where
lookupMatch m =
case lookupEntity (L.unpack . L.tail . L.init $ m) of
Nothing -> m
Just x -> UTF8.fromString [x]
-- regex replace taken from http://mutelight.org/articles/generating-a-permalink-slug-in-haskell
regexReplaceBy :: L.ByteString -> (L.ByteString -> L.ByteString) -> L.ByteString -> L.ByteString
regexReplaceBy regex f text = go text []
where
go str res =
if L.null str
then L.concat . reverse $ res
else
case (str =~~ regex) :: Maybe (L.ByteString, L.ByteString, L.ByteString) of
Nothing -> L.concat . reverse $ (str : res)
Just (bef, match , aft) -> go aft (f match : bef : res)
Функция unescapeEntities
работает на несколько порядков медленнее, чем Pythonверсия выше.Код Python может преобразовать около 130 МБ за 7 секунд, в то время как моя версия на Haskell работает в течение нескольких минут.
Я ищу лучшее решение, прежде всего с точки зрения скорости.Но я также хотел бы избегать регулярных выражений, если это возможно (скорость и избегание регулярных выражений в Хаскеле, похоже, идут рука об руку).