Note that there are some explanatory texts on larger screens.

plurals
  1. POUnescaping HTML entities (including named ones)
    primarykey
    data
    text
    <p>This question is similar to the <a href="https://stackoverflow.com/questions/4218205/haskell-remove-html-character-entities-in-a-string">Remove html character entities in a string</a> question asked earlier on Stack Overflow. <strong>The accepted answer, however, does not address the issue of named HTML entities, e.g. <code>&amp;auml;</code> for the character <code>ä</code>;</strong> It therefore cannot unescape all HTML.</p> <p>I have some legacy HTML which uses named HTML entities for non-ASCII characters. That is, <code>&amp;ouml;</code> instead of <code>ö</code>, <code>&amp;auml;</code> instead of <code>ä</code> and so on. <a href="http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references" rel="nofollow noreferrer">A full list of all named HTML entities</a> is available on Wikipedia.</p> <p>I'd like to unescape these HTML entities into their character equivalents, in a quick and efficient manner.</p> <hr> <p>I have the code to do this in Python 3, using regular expressions:</p> <pre><code>import re import html.entities s = re.sub(r'&amp;(\w+?);', lambda m: chr(html.entities.name2codepoint[m.group(1)]), s) </code></pre> <p>Regular expressions, however, don't seem very popular, fast or easy to use in Haskell.</p> <hr> <p><code>Text.HTML.TagSoup.Entity</code> (tagsoup) has a useful table and functions for mapping named entities tpo codepoints. Using this, and the regex-tdfa package, I've fashioned an <em>extremely slow</em> equivalent in Haskell:</p> <pre><code>{-# 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 -&gt; L.ByteString unescapeEntites = regexReplaceBy "&amp;#?[[:alnum:]]+;" $ lookupMatch where lookupMatch m = case lookupEntity (L.unpack . L.tail . L.init $ m) of Nothing -&gt; m Just x -&gt; UTF8.fromString [x] -- regex replace taken from http://mutelight.org/articles/generating-a-permalink-slug-in-haskell regexReplaceBy :: L.ByteString -&gt; (L.ByteString -&gt; L.ByteString) -&gt; L.ByteString -&gt; 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 -&gt; L.concat . reverse $ (str : res) Just (bef, match , aft) -&gt; go aft (f match : bef : res) </code></pre> <p>The <code>unescapeEntities</code> function runs several orders of magnitude slower than the Python version above. The Python code can convert about 130 MB in 7 seconds, whereas my Haskell version runs for several minutes.</p> <p>I'm looking for a better solution, primarily in terms of speed. But I'd also like to avoid regular expressions, if possible (speed and avoiding regular expressions seem to go hand in hand in Haskell anyway).</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload