diff -r ae8b054155c1 Lib/test/test_xml_etree.py
--- a/Lib/test/test_xml_etree.py Sat Jul 06 10:25:04 2013 +0200
+++ b/Lib/test/test_xml_etree.py Sun Jul 07 16:19:16 2013 +0200
@@ -79,6 +79,20 @@
"""
+SAMPLE_PRETTYPRINTED_XML = """\
+
+ text
+ tail
+
+
+ prefixtext
+ text
+ tail
+
+
+\
+"""
+
ENTITY_XML = """\
@@ -668,6 +682,18 @@
elem = ET.fromstring("text")
self.assertEqual(ET.tostring(elem), b'text')
+ def _munge_whitespace(self, elem):
+ elem.text = ' %s ' % elem.text.strip() if elem.text else ' '
+ elem.tail = ' %s ' % elem.tail.strip() if elem.tail else ' '
+ for e in elem:
+ self._munge_whitespace(e)
+
+ def test_prettyprint(self):
+ elem = ET.fromstring(SAMPLE_PRETTYPRINTED_XML)
+ self._munge_whitespace(elem)
+ prettyprinted = ET.tostring(elem, pretty=True)
+ self.assertEqual(prettyprinted, bytes(SAMPLE_PRETTYPRINTED_XML, 'utf8'))
+
def test_encoding(self):
def check(encoding, body=''):
xml = ("%s" %
diff -r ae8b054155c1 Lib/xml/etree/ElementTree.py
--- a/Lib/xml/etree/ElementTree.py Sat Jul 06 10:25:04 2013 +0200
+++ b/Lib/xml/etree/ElementTree.py Sun Jul 07 16:19:16 2013 +0200
@@ -723,7 +723,8 @@
xml_declaration=None,
default_namespace=None,
method=None, *,
- short_empty_elements=True):
+ short_empty_elements=True,
+ pretty=False):
"""Write element tree to a file as XML.
Arguments:
@@ -746,6 +747,9 @@
tag, otherwise they are emitted as a pair
of start/end tags
+ *pretty* -- enables human-readable indentation where relevant.
+ Off by default.
+
"""
if not method:
method = "xml"
@@ -775,7 +779,8 @@
qnames, namespaces = _namespaces(self._root, default_namespace)
serialize = _serialize[method]
serialize(write, self._root, qnames, namespaces,
- short_empty_elements=short_empty_elements)
+ short_empty_elements=short_empty_elements,
+ pretty=pretty, depth=0)
def write_c14n(self, file):
# lxml.etree compatibility. use output method instead
@@ -898,7 +903,10 @@
return qnames, namespaces
def _serialize_xml(write, elem, qnames, namespaces,
- short_empty_elements, **kwargs):
+ short_empty_elements, pretty, depth,
+ tail_depth=None, **kwargs):
+ if tail_depth is None:
+ tail_depth = depth and (depth - 1)
tag = elem.tag
text = elem.text
if tag is Comment:
@@ -906,13 +914,24 @@
elif tag is ProcessingInstruction:
write("%s?>" % text)
else:
+ if pretty:
+ text = text and text.strip()
+ if len(elem):
+ indent = '\n' + ' ' * (depth + 1)
+ if text:
+ text = indent + text + indent
+ else:
+ text = indent
tag = qnames[tag]
if tag is None:
if text:
write(_escape_cdata(text))
- for e in elem:
+ for n, e in enumerate(elem):
+ new_tail_depth = depth if n + 1 == len(elem) else depth + 1
_serialize_xml(write, e, qnames, None,
- short_empty_elements=short_empty_elements)
+ short_empty_elements=short_empty_elements,
+ pretty=pretty, depth=depth + 1,
+ tail_depth=new_tail_depth)
else:
write("<" + tag)
items = list(elem.items())
@@ -938,14 +957,25 @@
write(">")
if text:
write(_escape_cdata(text))
- for e in elem:
+ for n, e in enumerate(elem):
+ new_tail_depth = depth if n + 1 == len(elem) else depth + 1
_serialize_xml(write, e, qnames, None,
- short_empty_elements=short_empty_elements)
+ short_empty_elements=short_empty_elements,
+ pretty=pretty, depth=depth + 1,
+ tail_depth=new_tail_depth)
write("" + tag + ">")
else:
write(" />")
- if elem.tail:
- write(_escape_cdata(elem.tail))
+ tail = elem.tail
+ if pretty:
+ tail = tail and tail.strip()
+ tail_indent = '\n' + ' ' * tail_depth if depth else ''
+ if tail:
+ tail = '\n' + ' ' * depth + tail + tail_indent
+ else:
+ tail = tail_indent
+ if tail:
+ write(_escape_cdata(tail))
HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr",
"img", "input", "isindex", "link", "meta", "param")
@@ -1108,7 +1138,8 @@
# --------------------------------------------------------------------
def tostring(element, encoding=None, method=None, *,
- short_empty_elements=True):
+ short_empty_elements=True,
+ pretty=False):
"""Generate string representation of XML element.
All subelements are included. If encoding is "unicode", a string
@@ -1123,7 +1154,8 @@
"""
stream = io.StringIO() if encoding == 'unicode' else io.BytesIO()
ElementTree(element).write(stream, encoding, method=method,
- short_empty_elements=short_empty_elements)
+ short_empty_elements=short_empty_elements,
+ pretty=pretty)
return stream.getvalue()
class _ListDataStream(io.BufferedIOBase):
@@ -1144,11 +1176,13 @@
return len(self.lst)
def tostringlist(element, encoding=None, method=None, *,
- short_empty_elements=True):
+ short_empty_elements=True,
+ pretty=False):
lst = []
stream = _ListDataStream(lst)
ElementTree(element).write(stream, encoding, method=method,
- short_empty_elements=short_empty_elements)
+ short_empty_elements=short_empty_elements,
+ pretty=pretty)
return lst