@@ -0,0 +1,279 @@
+#
+# SimpleXMLWriter
+# $Id: SimpleXMLWriter.py 2312 2005-03-02 18:13:39Z fredrik $
+#
+# a simple XML writer
+#
+# history:
+# 2001-12-28 fl created
+# 2002-11-25 fl fixed attribute encoding
+# 2002-12-02 fl minor fixes for 1.5.2
+# 2004-06-17 fl added pythondoc markup
+# 2004-07-23 fl added flush method (from Jay Graves)
+# 2004-10-03 fl added declaration method
+#
+# Copyright (c) 2001-2004 by Fredrik Lundh
+#
+# fredrik@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The SimpleXMLWriter module is
+#
+# Copyright (c) 2001-2004 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+##
+# Tools to write XML files, without having to deal with encoding
+# issues, well-formedness, etc.
+# <p>
+# The current version does not provide built-in support for
+# namespaces. To create files using namespaces, you have to provide
+# "xmlns" attributes and explicitly add prefixes to tags and
+# attributes.
+#
+# <h3>Patterns</h3>
+#
+# The following example generates a small XHTML document.
+# <pre>
+#
+# from elementtree.SimpleXMLWriter import XMLWriter
+# import sys
+#
+# w = XMLWriter(sys.stdout)
+#
+# html = w.start("html")
+#
+# w.start("head")
+# w.element("title", "my document")
+# w.element("meta", name="generator", value="my application 1.0")
+# w.end()
+#
+# w.start("body")
+# w.element("h1", "this is a heading")
+# w.element("p", "this is a paragraph")
+#
+# w.start("p")
+# w.data("this is ")
+# w.element("b", "bold")
+# w.data(" and ")
+# w.element("i", "italic")
+# w.data(".")
+# w.end("p")
+#
+# w.close(html)
+# </pre>
+##
+
+import re, sys, string
+
+try:
+ unicode("")
+except NameError:
+ def encode(s, encoding):
+ # 1.5.2: application must use the right encoding
+ return s
+ _escape = re.compile(r"[&<>\"\x80-\xff]+") # 1.5.2
+else:
+ def encode(s, encoding):
+ return s.encode(encoding)
+ _escape = re.compile(eval(r'u"[&<>\"\u0080-\uffff]+"'))
+
+def encode_entity(text, pattern=_escape):
+ # map reserved and non-ascii characters to numerical entities
+ def escape_entities(m):
+ out = []
+ for char in m.group():
+ out.append("&#%d;" % ord(char))
+ return string.join(out, "")
+ return encode(pattern.sub(escape_entities, text), "ascii")
+
+del _escape
+
+#
+# the following functions assume an ascii-compatible encoding
+# (or "utf-16")
+
+def escape_cdata(s, encoding=None, replace=string.replace):
+ s = replace(s, "&", "&")
+ s = replace(s, "<", "<")
+ s = replace(s, ">", ">")
+ if encoding:
+ try:
+ return encode(s, encoding)
+ except UnicodeError:
+ return encode_entity(s)
+ return s
+
+def escape_attrib(s, encoding=None, replace=string.replace):
+ s = replace(s, "&", "&")
+ s = replace(s, "'", "'")
+ s = replace(s, "\"", """)
+ s = replace(s, "<", "<")
+ s = replace(s, ">", ">")
+ if encoding:
+ try:
+ return encode(s, encoding)
+ except UnicodeError:
+ return encode_entity(s)
+ return s
+
+##
+# XML writer class.
+#
+# @param file A file or file-like object. This object must implement
+# a <b>write</b> method that takes an 8-bit string.
+# @param encoding Optional encoding.
+
+class XMLWriter:
+
+ def __init__(self, file, encoding="us-ascii"):
+ if not hasattr(file, "write"):
+ file = open(file, "w")
+ self.__write = file.write
+ if hasattr(file, "flush"):
+ self.flush = file.flush
+ self.__open = 0 # true if start tag is open
+ self.__tags = []
+ self.__data = []
+ self.__encoding = encoding
+
+ def __flush(self):
+ # flush internal buffers
+ if self.__open:
+ self.__write(">")
+ self.__open = 0
+ if self.__data:
+ data = string.join(self.__data, "")
+ self.__write(escape_cdata(data, self.__encoding))
+ self.__data = []
+
+ ##
+ # Writes an XML declaration.
+
+ def declaration(self):
+ encoding = self.__encoding
+ if encoding == "us-ascii" or encoding == "utf-8":
+ self.__write("<?xml version='1.0'?>\n")
+ else:
+ self.__write("<?xml version='1.0' encoding='%s'?>\n" % encoding)
+
+ ##
+ # Opens a new element. Attributes can be given as keyword
+ # arguments, or as a string/string dictionary. You can pass in
+ # 8-bit strings or Unicode strings; the former are assumed to use
+ # the encoding passed to the constructor. The method returns an
+ # opaque identifier that can be passed to the <b>close</b> method,
+ # to close all open elements up to and including this one.
+ #
+ # @param tag Element tag.
+ # @param attrib Attribute dictionary. Alternatively, attributes
+ # can be given as keyword arguments.
+ # @return An element identifier.
+
+ def start(self, tag, attrib={}, **extra):
+ self.__flush()
+ tag = escape_cdata(tag, self.__encoding)
+ self.__data = []
|