diff -r f1b5fc67524a Doc/library/xml.sax.utils.rst
--- a/Doc/library/xml.sax.utils.rst Tue May 29 18:44:17 2012 -0500
+++ b/Doc/library/xml.sax.utils.rst Wed May 30 10:56:41 2012 +0300
@@ -50,13 +50,14 @@
using the reference concrete syntax.
-.. class:: XMLGenerator(out=None, encoding='iso-8859-1', short_empty_elements=False)
+.. class:: XMLGenerator(out=None, encoding=None, short_empty_elements=False)
This class implements the :class:`ContentHandler` interface by writing SAX
events back into an XML document. In other words, using an :class:`XMLGenerator`
as the content handler will reproduce the original document being parsed. *out*
- should be a file-like object which will default to *sys.stdout*. *encoding* is
- the encoding of the output stream which defaults to ``'iso-8859-1'``.
+ should be a :term:`file object` which will default to *sys.stdout*.
+ *encoding* is the encoding of the binary output stream.
+ Use ``encoding=None`` (which will default) to write to the text output stream.
*short_empty_elements* controls the formatting of elements that contain no
content: if *False* (the default) they are emitted as a pair of start/end
tags, if set to *True* they are emitted as a single self-closed tag.
diff -r f1b5fc67524a Lib/test/test_sax.py
--- a/Lib/test/test_sax.py Tue May 29 18:44:17 2012 -0500
+++ b/Lib/test/test_sax.py Wed May 30 10:56:41 2012 +0300
@@ -158,7 +158,7 @@
# ===== XMLGenerator
-start = '\n'
+start = '\n'
class XmlgenTest(unittest.TestCase):
def test_xmlgen_basic(self):
diff -r f1b5fc67524a Lib/test/xmltestdata/test.xml.out
--- a/Lib/test/xmltestdata/test.xml.out Tue May 29 18:44:17 2012 -0500
+++ b/Lib/test/xmltestdata/test.xml.out Wed May 30 10:56:41 2012 +0300
@@ -1,4 +1,4 @@
-
+
Introduction to XSL
Introduction to XSL
diff -r f1b5fc67524a Lib/xml/sax/saxutils.py
--- a/Lib/xml/sax/saxutils.py Tue May 29 18:44:17 2012 -0500
+++ b/Lib/xml/sax/saxutils.py Wed May 30 10:56:41 2012 +0300
@@ -4,6 +4,7 @@
"""
import os, urllib.parse, urllib.request
+import io
from . import handler
from . import xmlreader
@@ -78,11 +79,28 @@
class XMLGenerator(handler.ContentHandler):
- def __init__(self, out=None, encoding="iso-8859-1", short_empty_elements=False):
+ def __init__(self, out=None, encoding=None, short_empty_elements=False):
+ handler.ContentHandler.__init__(self)
if out is None:
import sys
out = sys.stdout
- handler.ContentHandler.__init__(self)
+ if encoding is not None:
+ out = out.buffer.raw
+ if encoding is not None:
+ if not isinstance(out, io.BufferedIOBase):
+ writer = out
+ out = io.BufferedIOBase()
+ out.writable = lambda: True
+ out.write = writer.write
+ try:
+ # Required to write BOM
+ out.seekable = writer.seekable
+ out.tell = writer.tell
+ except AttributeError:
+ pass
+ out = io.TextIOWrapper(out, encoding=encoding,
+ errors=_error_handling,
+ newline="\n")
self._out = out
self._ns_contexts = [{}] # contains uri -> prefix dicts
self._current_context = self._ns_contexts[-1]
@@ -91,12 +109,6 @@
self._short_empty_elements = short_empty_elements
self._pending_start_element = False
- def _write(self, text):
- if isinstance(text, str):
- self._out.write(text)
- else:
- self._out.write(text.encode(self._encoding, _error_handling))
-
def _qname(self, name):
"""Builds a qualified name from a (ns_url, localname) pair"""
if name[0]:
@@ -116,14 +128,21 @@
def _finish_pending_start_element(self,endElement=False):
if self._pending_start_element:
- self._write('>')
+ self._out.write('>')
self._pending_start_element = False
# ContentHandler methods
def startDocument(self):
- self._write('\n' %
- self._encoding)
+ if self._encoding is not None:
+ self._out.write('\n' %
+ self._encoding)
+ else:
+ self._out.write('\n')
+
+ def endDocument(self):
+ if self._encoding is not None:
+ self._out.detach()
def startPrefixMapping(self, prefix, uri):
self._ns_contexts.append(self._current_context.copy())
@@ -136,24 +155,24 @@
def startElement(self, name, attrs):
self._finish_pending_start_element()
- self._write('<' + name)
+ self._out.write('<' + name)
for (name, value) in attrs.items():
- self._write(' %s=%s' % (name, quoteattr(value)))
+ self._out.write(' %s=%s' % (name, quoteattr(value)))
if self._short_empty_elements:
self._pending_start_element = True
else:
- self._write(">")
+ self._out.write(">")
def endElement(self, name):
if self._pending_start_element:
- self._write('/>')
+ self._out.write('/>')
self._pending_start_element = False
else:
- self._write('%s>' % name)
+ self._out.write('%s>' % name)
def startElementNS(self, name, qname, attrs):
self._finish_pending_start_element()
- self._write('<' + self._qname(name))
+ self._out.write('<' + self._qname(name))
for prefix, uri in self._undeclared_ns_maps:
if prefix:
@@ -163,32 +182,32 @@
self._undeclared_ns_maps = []
for (name, value) in attrs.items():
- self._write(' %s=%s' % (self._qname(name), quoteattr(value)))
+ self._out.write(' %s=%s' % (self._qname(name), quoteattr(value)))
if self._short_empty_elements:
self._pending_start_element = True
else:
- self._write(">")
+ self._out.write(">")
def endElementNS(self, name, qname):
if self._pending_start_element:
- self._write('/>')
+ self._out.write('/>')
self._pending_start_element = False
else:
- self._write('%s>' % self._qname(name))
+ self._out.write('%s>' % self._qname(name))
def characters(self, content):
if content:
self._finish_pending_start_element()
- self._write(escape(content))
+ self._out.write(escape(content))
def ignorableWhitespace(self, content):
if content:
self._finish_pending_start_element()
- self._write(content)
+ self._out.write(content)
def processingInstruction(self, target, data):
self._finish_pending_start_element()
- self._write('%s %s?>' % (target, data))
+ self._out.write('%s %s?>' % (target, data))
class XMLFilterBase(xmlreader.XMLReader):