diff --git a/sat/plugins/plugin_misc_text_syntaxes.py b/sat/plugins/plugin_misc_text_syntaxes.py index 455f48d0..9a4208ae 100755 --- a/sat/plugins/plugin_misc_text_syntaxes.py +++ b/sat/plugins/plugin_misc_text_syntaxes.py @@ -31,6 +31,7 @@ from sat.tools import xml_tools try: from lxml import html from lxml.html import clean + from lxml import etree except ImportError: raise exceptions.MissingModule( u"Missing module lxml, please download/install it from http://lxml.de/" @@ -95,6 +96,25 @@ STYLES_WHITELIST = ( "width", ) +# cf. https://www.w3.org/TR/html/syntax.html#void-elements +VOID_ELEMENTS = ( + "area", + "base", + "br", + "col", + "embed", + "hr", + "img", + "input", + "keygen", + "link", + "menuitem", + "meta", + "param", + "source", + "track", + "wbr") + SAFE_ATTRS = html.defs.safe_attrs.union(("style", "poster", "controls")) STYLES_VALUES_REGEX = ( r"^(" @@ -279,7 +299,13 @@ class TextSyntaxes(object): """ if isinstance(xhtml, basestring): - xhtml_elt = html.fromstring(xhtml) + try: + xhtml_elt = html.fromstring(xhtml) + except etree.ParserError as e: + if not xhtml.strip(): + return u"" + log.error(u"Can't clean XHTML: {xhtml}".format(xhtml=xhtml)) + raise e elif isinstance(xhtml, html.HtmlElement): xhtml_elt = xhtml else: @@ -291,6 +317,13 @@ class TextSyntaxes(object): xhtml_elt = cleaner.clean_html(xhtml_elt) for elt in xhtml_elt.xpath("//*[@style]"): elt.set("style", self.cleanStyle(elt.get("style"))) + # we remove self-closing elements for non-void elements + for element in xhtml_elt.iter(tag=etree.Element): + if not element.text: + if element.tag in VOID_ELEMENTS: + element.text = None + else: + element.text = u'' return html.tostring(xhtml_elt, encoding=unicode, method="xml") def convert(