15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# markdown is released under the BSD license
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright 2004 Manfred Stienstra (the original version)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# All rights reserved.
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Redistribution and use in source and binary forms, with or without
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# modification, are permitted provided that the following conditions are met:
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# *   Redistributions of source code must retain the above copyright
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#     notice, this list of conditions and the following disclaimer.
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# *   Redistributions in binary form must reproduce the above copyright
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#     notice, this list of conditions and the following disclaimer in the
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#     documentation and/or other materials provided with the distribution.
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# *   Neither the name of the <organization> nor the
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#     names of its contributors may be used to endorse or promote products
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#     derived from this software without specific prior written permission.
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY THE PYTHON MARKDOWN PROJECT ''AS IS'' AND ANY
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# DISCLAIMED. IN NO EVENT SHALL ANY CONTRIBUTORS TO THE PYTHON MARKDOWN PROJECT
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# POSSIBILITY OF SUCH DAMAGE.
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# markdown/searializers.py
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Add x/html serialization to Elementree
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Taken from ElementTree 1.3 preview with slight modifications
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright (c) 1999-2007 by Fredrik Lundh.  All rights reserved.
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# fredrik@pythonware.com
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# http://www.pythonware.com
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# --------------------------------------------------------------------
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# The ElementTree toolkit is
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Copyright (c) 1999-2007 by Fredrik Lundh
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# By obtaining, using, and/or copying this software and/or its
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# associated documentation, you agree that you have read, understood,
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# and will comply with the following terms and conditions:
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Permission to use, copy, modify, and distribute this software and
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# its associated documentation for any purpose and without fee is
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# hereby granted, provided that the above copyright notice appears in
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# all copies, and that both that copyright notice and this permission
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# notice appear in supporting documentation, and that the name of
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# Secret Labs AB or the author not be used in advertising or publicity
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# pertaining to distribution of the software without specific, written
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# prior permission.
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# OF THIS SOFTWARE.
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# --------------------------------------------------------------------
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from __future__ import absolute_import
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from __future__ import unicode_literals
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)from . import util
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ElementTree = util.etree.ElementTree
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QName = util.etree.QName
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)if hasattr(util.etree, 'test_comment'):
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Comment = util.etree.test_comment
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)else:
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Comment = util.etree.Comment
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)PI = util.etree.PI
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ProcessingInstruction = util.etree.ProcessingInstruction
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)__all__ = ['to_html_string', 'to_xhtml_string']
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr",
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              "img", "input", "isindex", "link", "meta" "param")
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)try:
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    HTML_EMPTY = set(HTML_EMPTY)
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)except NameError:
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pass
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)_namespace_map = {
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # "well-known" namespace prefixes
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "http://www.w3.org/XML/1998/namespace": "xml",
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "http://www.w3.org/1999/xhtml": "html",
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "http://schemas.xmlsoap.org/wsdl/": "wsdl",
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # xml schema
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "http://www.w3.org/2001/XMLSchema": "xs",
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "http://www.w3.org/2001/XMLSchema-instance": "xsi",
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # dublic core
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "http://purl.org/dc/elements/1.1/": "dc",
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def _raise_serialization_error(text):
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    raise TypeError(
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        "cannot serialize %r (type %s)" % (text, type(text).__name__)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        )
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def _encode(text, encoding):
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    try:
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return text.encode(encoding, "xmlcharrefreplace")
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    except (TypeError, AttributeError):
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        _raise_serialization_error(text)
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def _escape_cdata(text):
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # escape character data
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    try:
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # it's worth avoiding do-nothing calls for strings that are
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # shorter than 500 character, or so.  assume that's, by far,
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # the most common case in most applications.
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if "&" in text:
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace("&", "&amp;")
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if "<" in text:
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace("<", "&lt;")
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if ">" in text:
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace(">", "&gt;")
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return text
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    except (TypeError, AttributeError):
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        _raise_serialization_error(text)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def _escape_attrib(text):
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # escape attribute value
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    try:
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if "&" in text:
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace("&", "&amp;")
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if "<" in text:
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace("<", "&lt;")
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if ">" in text:
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace(">", "&gt;")
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if "\"" in text:
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace("\"", "&quot;")
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if "\n" in text:
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace("\n", "&#10;")
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return text
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    except (TypeError, AttributeError):
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        _raise_serialization_error(text)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def _escape_attrib_html(text):
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # escape attribute value
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    try:
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if "&" in text:
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace("&", "&amp;")
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if "<" in text:
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace("<", "&lt;")
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if ">" in text:
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace(">", "&gt;")
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if "\"" in text:
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            text = text.replace("\"", "&quot;")
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return text
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    except (TypeError, AttributeError):
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        _raise_serialization_error(text)
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def _serialize_html(write, elem, qnames, namespaces, format):
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    tag = elem.tag
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    text = elem.text
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if tag is Comment:
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        write("<!--%s-->" % _escape_cdata(text))
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    elif tag is ProcessingInstruction:
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        write("<?%s?>" % _escape_cdata(text))
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else:
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        tag = qnames[tag]
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if tag is None:
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if text:
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                write(_escape_cdata(text))
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            for e in elem:
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                _serialize_html(write, e, qnames, None, format)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        else:
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            write("<" + tag)
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            items = elem.items()
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if items or namespaces:
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                items.sort() # lexical order
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                for k, v in items:
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if isinstance(k, QName):
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        k = k.text
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if isinstance(v, QName):
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        v = qnames[v.text]
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    else:
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        v = _escape_attrib_html(v)
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if qnames[k] == v and format == 'html':
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        # handle boolean attributes
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        write(" %s" % v)
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    else:
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        write(" %s=\"%s\"" % (qnames[k], v))
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if namespaces:
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    items = namespaces.items()
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    items.sort(key=lambda x: x[1]) # sort on prefix
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    for v, k in items:
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        if k:
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            k = ":" + k
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        write(" xmlns%s=\"%s\"" % (k, _escape_attrib(v)))
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if format == "xhtml" and tag in HTML_EMPTY:
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                write(" />")
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            else:
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                write(">")
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                tag = tag.lower()
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if text:
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if tag == "script" or tag == "style":
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        write(text)
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    else:
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        write(_escape_cdata(text))
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                for e in elem:
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    _serialize_html(write, e, qnames, None, format)
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if tag not in HTML_EMPTY:
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    write("</" + tag + ">")
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if elem.tail:
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        write(_escape_cdata(elem.tail))
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def _write_html(root,
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                encoding=None,
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                default_namespace=None,
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                format="html"):
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert root is not None
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    data = []
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    write = data.append
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    qnames, namespaces = _namespaces(root, default_namespace)
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    _serialize_html(write, root, qnames, namespaces, format)
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if encoding is None:
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return "".join(data)
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    else:
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return _encode("".join(data))
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# --------------------------------------------------------------------
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)# serialization support
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def _namespaces(elem, default_namespace=None):
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # identify namespaces used in this tree
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # maps qnames to *encoded* prefix:local names
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    qnames = {None: None}
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # maps uri:s to prefixes
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    namespaces = {}
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if default_namespace:
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        namespaces[default_namespace] = ""
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    def add_qname(qname):
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        # calculate serialized qname representation
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        try:
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if qname[:1] == "{":
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                uri, tag = qname[1:].split("}", 1)
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                prefix = namespaces.get(uri)
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if prefix is None:
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    prefix = _namespace_map.get(uri)
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if prefix is None:
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        prefix = "ns%d" % len(namespaces)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    if prefix != "xml":
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        namespaces[uri] = prefix
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if prefix:
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    qnames[qname] = "%s:%s" % (prefix, tag)
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                else:
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    qnames[qname] = tag # default element
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            else:
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                if default_namespace:
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    raise ValueError(
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        "cannot use non-qualified names with "
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        "default_namespace option"
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        )
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                qnames[qname] = qname
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        except TypeError:
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            _raise_serialization_error(qname)
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    # populate qname and namespaces table
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    try:
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        iterate = elem.iter
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    except AttributeError:
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        iterate = elem.getiterator # cET compatibility
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for elem in iterate():
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        tag = elem.tag
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if isinstance(tag, QName) and tag.text not in qnames:
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            add_qname(tag.text)
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        elif isinstance(tag, util.string_type):
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if tag not in qnames:
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                add_qname(tag)
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        elif tag is not None and tag is not Comment and tag is not PI:
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            _raise_serialization_error(tag)
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        for key, value in elem.items():
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if isinstance(key, QName):
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                key = key.text
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if key not in qnames:
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                add_qname(key)
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if isinstance(value, QName) and value.text not in qnames:
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                add_qname(value.text)
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        text = elem.text
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if isinstance(text, QName) and text.text not in qnames:
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            add_qname(text.text)
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return qnames, namespaces
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def to_html_string(element):
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return _write_html(ElementTree(element).getroot(), format="html")
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def to_xhtml_string(element):
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return _write_html(ElementTree(element).getroot(), format="xhtml")
310