Differences between revisions 16 and 22 (spanning 6 versions)
Revision 16 as of 2007-04-10 00:03:58
Size: 2417
Comment: Remove pointless comment; if there's a problem with the examples, explain it!
Revision 22 as of 2009-03-26 21:40:23
Size: 3145
Editor: rdns
Comment: HTML quoting built-in - xml.sax.saxutils quoteattr(data)
Deletions are marked like this. Additions are marked like this.
Line 15: Line 15:
Here's a small snippet that will let you escape those as well: Here's a small snippet that will let you escape quotes and apostrophes as well:
Line 34: Line 34:

If you are using Python 2.2 or better, this is built into the xml.sax.saxutils quoteattr(data) function.
Line 77: Line 79:

== Formal htmlentitydefs ==
Yet another approach available with recent Python takes advantage
of htmlentitydefs:
{{{
import re
from htmlentitydefs import name2codepoint
def htmlentitydecode(s):
    return re.sub('&(%s);' % '|'.join(name2codepoint),
            lambda m: unichr(name2codepoint[m.group(1)]), s)
}}}
Line 79: Line 93:
XML entities are different from, if related to, HTML entities.
This page hints at the details:
Line 80: Line 96:

John J. Lee discusses still more refinements in implementation in
[[http://groups.google.com/group/comp.lang.python/msg/ce3fc3330cbbac0a|this comp.lang.python follow-up]].

Escaping HTML

The cgi module that comes with Python has an escape() function:

   1 import cgi
   2 
   3 s = cgi.escape( """& < >""" )   # s = "&amp; &lt; &gt;"

However, it doesn't escape characters beyond &, <, and >.

Here's a small snippet that will let you escape quotes and apostrophes as well:

   1 html_escape_table = {
   2     "&": "&amp;",
   3     '"': "&quot;",
   4     "'": "&apos;",
   5     ">": "&gt;",
   6     "<": "&lt;",
   7     }
   8 
   9 def html_escape(text):
  10     """Produce entities within text."""
  11     L=[]
  12     for c in text:
  13         L.append(html_escape_table.get(c,c))
  14     return "".join(L)

If you are using Python 2.2 or better, this is built into the xml.sax.saxutils quoteattr(data) function.

Unescaping HTML

Undoing the escaping performed by cgi.escape() isn't directly supported by the library. This can be accomplished using a fairly simple function, however:

   1 def unescape(s):
   2     s = s.replace("&lt;", "<")
   3     s = s.replace("&gt;", ">")
   4     # this has to be last:
   5     s = s.replace("&amp;", "&")
   6     return s

Note that this will undo exactly what cgi.escape() does; it's easy to extend this to undo what the html_escape() function above does. Note the comment that converting the &amp; must be last; this avoids getting strings like "&amp;lt;" wrong.

This approach is simple and fairly efficient, but is limited to supporting the entities given in the list. A more thorough approach would be to perform the same processing as an HTML parser. Using the HTML parser from the standard library is a little more expensive, but many more entity replacements are supported "out of the box." The table of entities which are supported can be found in the htmlentitydefs module from the library; this is not normally used directly, but the htmllib module uses it to support most common entities. It can be used very easily:

   1 import htmllib
   2 
   3 def unescape(s):
   4     p = htmllib.HTMLParser(None)
   5     p.save_bgn()
   6     p.feed(s)
   7     return p.save_end()

This version has the additional advantage that it supports character references (things like &#65;) as well as entity references.

A more efficient implementation would simply parse the string for entity and character references directly (and would be a good candidate for the library, if there's really a need for it outside of HTML data).

Formal htmlentitydefs

Yet another approach available with recent Python takes advantage of htmlentitydefs:

import re
from htmlentitydefs import name2codepoint
def htmlentitydecode(s):
    return re.sub('&(%s);' % '|'.join(name2codepoint), 
            lambda m: unichr(name2codepoint[m.group(1)]), s)

See Also

XML entities are different from, if related to, HTML entities. This page hints at the details:

John J. Lee discusses still more refinements in implementation in this comp.lang.python follow-up.

EscapingHtml (last edited 2016-11-19 12:13:41 by OleskandrGavenko)

Unable to edit the page? See the FrontPage for instructions.