16516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# markdown/html4.py
26516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru#
36516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# Add html4 serialization to older versions of Elementree
46516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# Taken from ElementTree 1.3 preview with slight modifications
56516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru#
66516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# Copyright (c) 1999-2007 by Fredrik Lundh.  All rights reserved.
76516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru#
86516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# fredrik@pythonware.com
96516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# http://www.pythonware.com
106516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru#
116516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# --------------------------------------------------------------------
126516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# The ElementTree toolkit is
136516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru#
146516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# Copyright (c) 1999-2007 by Fredrik Lundh
156516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru#
166516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# By obtaining, using, and/or copying this software and/or its
176516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# associated documentation, you agree that you have read, understood,
186516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# and will comply with the following terms and conditions:
196516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru#
206516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# Permission to use, copy, modify, and distribute this software and
216516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# its associated documentation for any purpose and without fee is
226516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# hereby granted, provided that the above copyright notice appears in
236516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# all copies, and that both that copyright notice and this permission
246516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# notice appear in supporting documentation, and that the name of
256516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# Secret Labs AB or the author not be used in advertising or publicity
266516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# pertaining to distribution of the software without specific, written
276516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# prior permission.
286516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru#
296516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
306516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
316516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
326516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
336516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
346516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
356516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
366516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# OF THIS SOFTWARE.
376516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# --------------------------------------------------------------------
386516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
396516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
406516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queruimport markdown
416516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruElementTree = markdown.etree.ElementTree
426516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruQName = markdown.etree.QName
436516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruComment = markdown.etree.Comment
446516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruPI = markdown.etree.PI
456516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruProcessingInstruction = markdown.etree.ProcessingInstruction
466516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
476516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste QueruHTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr",
486516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru              "img", "input", "isindex", "link", "meta" "param")
496516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
506516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querutry:
516516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    HTML_EMPTY = set(HTML_EMPTY)
526516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queruexcept NameError:
536516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    pass
546516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
556516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru_namespace_map = {
566516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    # "well-known" namespace prefixes
576516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    "http://www.w3.org/XML/1998/namespace": "xml",
586516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    "http://www.w3.org/1999/xhtml": "html",
596516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
606516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    "http://schemas.xmlsoap.org/wsdl/": "wsdl",
616516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    # xml schema
626516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    "http://www.w3.org/2001/XMLSchema": "xs",
636516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    "http://www.w3.org/2001/XMLSchema-instance": "xsi",
646516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    # dublic core
656516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    "http://purl.org/dc/elements/1.1/": "dc",
666516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru}
676516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
686516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
696516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef _raise_serialization_error(text):
706516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    raise TypeError(
716516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        "cannot serialize %r (type %s)" % (text, type(text).__name__)
726516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        )
736516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
746516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef _encode(text, encoding):
756516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    try:
766516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        return text.encode(encoding, "xmlcharrefreplace")
776516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    except (TypeError, AttributeError):
786516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        _raise_serialization_error(text)
796516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
806516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef _escape_cdata(text, encoding):
816516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    # escape character data
826516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    try:
836516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        # it's worth avoiding do-nothing calls for strings that are
846516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        # shorter than 500 character, or so.  assume that's, by far,
856516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        # the most common case in most applications.
866516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if "&" in text:
876516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace("&", "&")
886516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if "<" in text:
896516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace("<", "&lt;")
906516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if ">" in text:
916516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace(">", "&gt;")
926516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        return text.encode(encoding, "xmlcharrefreplace")
936516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    except (TypeError, AttributeError):
946516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        _raise_serialization_error(text)
956516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
966516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
976516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef _escape_attrib(text, encoding):
986516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    # escape attribute value
996516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    try:
1006516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if "&" in text:
1016516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace("&", "&amp;")
1026516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if "<" in text:
1036516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace("<", "&lt;")
1046516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if ">" in text:
1056516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace(">", "&gt;")
1066516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if "\"" in text:
1076516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace("\"", "&quot;")
1086516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if "\n" in text:
1096516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace("\n", "&#10;")
1106516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        return text.encode(encoding, "xmlcharrefreplace")
1116516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    except (TypeError, AttributeError):
1126516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        _raise_serialization_error(text)
1136516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
1146516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef _escape_attrib_html(text, encoding):
1156516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    # escape attribute value
1166516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    try:
1176516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if "&" in text:
1186516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace("&", "&amp;")
1196516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if ">" in text:
1206516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace(">", "&gt;")
1216516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if "\"" in text:
1226516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            text = text.replace("\"", "&quot;")
1236516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        return text.encode(encoding, "xmlcharrefreplace")
1246516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    except (TypeError, AttributeError):
1256516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        _raise_serialization_error(text)
1266516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
1276516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
1286516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef _serialize_html(write, elem, encoding, qnames, namespaces):
1296516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    tag = elem.tag
1306516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    text = elem.text
1316516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    if tag is Comment:
1326516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        write("<!--%s-->" % _escape_cdata(text, encoding))
1336516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    elif tag is ProcessingInstruction:
1346516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        write("<?%s?>" % _escape_cdata(text, encoding))
1356516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    else:
1366516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        tag = qnames[tag]
1376516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if tag is None:
1386516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if text:
1396516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                write(_escape_cdata(text, encoding))
1406516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            for e in elem:
1416516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                _serialize_html(write, e, encoding, qnames, None)
1426516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        else:
1436516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            write("<" + tag)
1446516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            items = elem.items()
1456516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if items or namespaces:
1466516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                items.sort() # lexical order
1476516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                for k, v in items:
1486516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    if isinstance(k, QName):
1496516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        k = k.text
1506516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    if isinstance(v, QName):
1516516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        v = qnames[v.text]
1526516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    else:
1536516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        v = _escape_attrib_html(v, encoding)
1546516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    # FIXME: handle boolean attributes
1556516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    write(" %s=\"%s\"" % (qnames[k], v))
1566516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                if namespaces:
1576516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    items = namespaces.items()
1586516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    items.sort(key=lambda x: x[1]) # sort on prefix
1596516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    for v, k in items:
1606516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        if k:
1616516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                            k = ":" + k
1626516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        write(" xmlns%s=\"%s\"" % (
1636516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                            k.encode(encoding),
1646516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                            _escape_attrib(v, encoding)
1656516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                            ))
1666516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            write(">")
1676516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            tag = tag.lower()
1686516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if text:
1696516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                if tag == "script" or tag == "style":
1706516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    write(_encode(text, encoding))
1716516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                else:
1726516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    write(_escape_cdata(text, encoding))
1736516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            for e in elem:
1746516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                _serialize_html(write, e, encoding, qnames, None)
1756516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if tag not in HTML_EMPTY:
1766516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                write("</" + tag + ">")
1776516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    if elem.tail:
1786516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        write(_escape_cdata(elem.tail, encoding))
1796516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
1806516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef write_html(root, f,
1816516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru          # keyword arguments
1826516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru          encoding="us-ascii",
1836516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru          default_namespace=None):
1846516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    assert root is not None
1856516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    if not hasattr(f, "write"):
1866516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        f = open(f, "wb")
1876516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    write = f.write
1886516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    if not encoding:
1896516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        encoding = "us-ascii"
1906516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    qnames, namespaces = _namespaces(
1916516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            root, encoding, default_namespace
1926516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            )
1936516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    _serialize_html(
1946516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                write, root, encoding, qnames, namespaces
1956516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                )
1966516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
1976516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# --------------------------------------------------------------------
1986516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru# serialization support
1996516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
2006516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef _namespaces(elem, encoding, default_namespace=None):
2016516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    # identify namespaces used in this tree
2026516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
2036516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    # maps qnames to *encoded* prefix:local names
2046516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    qnames = {None: None}
2056516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
2066516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    # maps uri:s to prefixes
2076516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    namespaces = {}
2086516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    if default_namespace:
2096516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        namespaces[default_namespace] = ""
2106516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
2116516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    def encode(text):
2126516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        return text.encode(encoding)
2136516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
2146516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    def add_qname(qname):
2156516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        # calculate serialized qname representation
2166516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        try:
2176516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if qname[:1] == "{":
2186516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                uri, tag = qname[1:].split("}", 1)
2196516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                prefix = namespaces.get(uri)
2206516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                if prefix is None:
2216516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    prefix = _namespace_map.get(uri)
2226516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    if prefix is None:
2236516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        prefix = "ns%d" % len(namespaces)
2246516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    if prefix != "xml":
2256516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        namespaces[uri] = prefix
2266516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                if prefix:
2276516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    qnames[qname] = encode("%s:%s" % (prefix, tag))
2286516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                else:
2296516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    qnames[qname] = encode(tag) # default element
2306516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            else:
2316516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                if default_namespace:
2326516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    # FIXME: can this be handled in XML 1.0?
2336516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                    raise ValueError(
2346516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        "cannot use non-qualified names with "
2356516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        "default_namespace option"
2366516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                        )
2376516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                qnames[qname] = encode(qname)
2386516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        except TypeError:
2396516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            _raise_serialization_error(qname)
2406516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
2416516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    # populate qname and namespaces table
2426516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    try:
2436516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        iterate = elem.iter
2446516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    except AttributeError:
2456516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        iterate = elem.getiterator # cET compatibility
2466516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    for elem in iterate():
2476516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        tag = elem.tag
2486516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if isinstance(tag, QName) and tag.text not in qnames:
2496516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            add_qname(tag.text)
2506516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        elif isinstance(tag, basestring):
2516516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if tag not in qnames:
2526516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                add_qname(tag)
2536516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        elif tag is not None and tag is not Comment and tag is not PI:
2546516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            _raise_serialization_error(tag)
2556516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        for key, value in elem.items():
2566516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if isinstance(key, QName):
2576516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                key = key.text
2586516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if key not in qnames:
2596516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                add_qname(key)
2606516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            if isinstance(value, QName) and value.text not in qnames:
2616516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru                add_qname(value.text)
2626516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        text = elem.text
2636516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        if isinstance(text, QName) and text.text not in qnames:
2646516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru            add_qname(text.text)
2656516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    return qnames, namespaces
2666516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru
2676516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Querudef to_html_string(element, encoding=None):
2686516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    class dummy:
2696516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru        pass
2706516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    data = []
2716516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    file = dummy()
2726516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    file.write = data.append
2736516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    write_html(ElementTree(element).getroot(),file,encoding)
2746516b99bb74dfb7187a08f7090bf7ca22a006f15Jean-Baptiste Queru    return "".join(data)
275