FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

bpo-14465: Provide simple prett printing for XML and ETree API by mcepl · Pull Request #8933 · python/cpython · GitHub

Repository navigation

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .py  (2) .rst  (2) All 2 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
18 changes: 17 additions & 1 deletion Doc/library/xml.etree.elementtree.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ Functions


.. function:: tostring(element, encoding="us-ascii", method="xml", *, \
pretty_print=False, \
short_empty_elements=True)

Generates a string representation of an XML element, including all
Expand All @@ -596,13 +597,18 @@ Functions
generate a Unicode string (otherwise, a bytestring is generated). *method*
is either ``"xml"``, ``"html"`` or ``"text"`` (default is ``"xml"``).
*short_empty_elements* has the same meaning as in :meth:`ElementTree.write`.
*pretty_print* enables pretty printing with default indent.
Returns an (optionally) encoded string containing the XML data.

.. versionadded:: 3.4
The *short_empty_elements* parameter.

.. versionadded:: 3.7
The *pretty_print* parameter.


.. function:: tostringlist(element, encoding="us-ascii", method="xml", *, \
pretty_print=False, \
short_empty_elements=True)

Generates a string representation of an XML element, including all
Expand All @@ -611,6 +617,7 @@ Functions
generate a Unicode string (otherwise, a bytestring is generated). *method*
is either ``"xml"``, ``"html"`` or ``"text"`` (default is ``"xml"``).
*short_empty_elements* has the same meaning as in :meth:`ElementTree.write`.
*pretty_print* enables pretty printing with default indent.
Returns a list of (optionally) encoded strings containing the XML data.
It does not guarantee any specific sequence, except that
``b"".join(tostringlist(element)) == tostring(element)``.
Expand All @@ -620,6 +627,9 @@ Functions
.. versionadded:: 3.4
The *short_empty_elements* parameter.

.. versionadded:: 3.7
The *pretty_print* parameter.


.. function:: XML(text, parser=None)

Expand Down Expand Up @@ -921,6 +931,7 @@ ElementTree Objects

.. method:: write(file, encoding="us-ascii", xml_declaration=None, \
default_namespace=None, method="xml", *, \
pretty_print=False, \
short_empty_elements=True)

Writes the element tree to a file, as XML. *file* is a file name, or a
Expand All @@ -935,7 +946,8 @@ ElementTree Objects
The keyword-only *short_empty_elements* parameter controls the formatting
of elements that contain no content. If ``True`` (the default), they are
emitted as a single self-closed tag, otherwise they are emitted as a pair
of start/end tags.
of start/end tags. *pretty_print* enables pretty printing
with default indent.

The output is either a string (:class:`str`) or binary (:class:`bytes`).
This is controlled by the *encoding* argument. If *encoding* is
Expand All @@ -947,6 +959,10 @@ ElementTree Objects
.. versionadded:: 3.4
The *short_empty_elements* parameter.

.. versionadded:: 3.7
The *pretty_print* parameter.



This is the XML file that is going to be manipulated::

Expand Down
74 changes: 74 additions & 0 deletions Lib/test/test_xml_etree.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,80 @@ def test_html_empty_elems_serialization(self):
method='html')
self.assertEqual(serialized, expected)

def test_pretty_print_xml(self):
comment = ET.Comment('comment')

root = ET.Element(None)

child1 = ET.SubElement(root, 'child1')
child1.append(comment)
elem = ET.SubElement(child1, 'elem')
elem.set('a', '1')
elem.set('b', 'txt')
elem.text = 'Oh, wow, some text!'

child2 = ET.SubElement(root, 'child2')
elem1 = ET.SubElement(child2, 'elem1')
elem21 = ET.SubElement(elem1, 'elem21')
elem22 = ET.SubElement(elem1, 'elem22')
elem3 = ET.SubElement(elem21, 'elem3')

elem22.append(comment)

observed = serialize(root, method='xml', pretty_print=True)
expected = '\n <child1>\n' + \
' <!--comment-->\n' + \
' <elem a="1" b="txt">Oh, wow, some text!</elem>\n' + \
' </child1>\n' + \
' <child2>\n' + \
' <elem1>\n' + \
' <elem21>\n' + \
' <elem3 />\n' + \
' </elem21>\n' + \
' <elem22>\n' + \
' <!--comment-->\n' + \
' </elem22>\n' + \
' </elem1>\n' + \
' </child2>\n'
self.assertEqual(observed, expected)

def test_pretty_print_html(self):
html = ET.Element('html')

head = ET.SubElement(html, 'head')
body = ET.SubElement(html, 'body')

style = ET.SubElement(head, 'style')
style.text = '''
body {background-color: white;}
h1 {color: blue;}
p {color: red;}
'''

p = ET.SubElement(body, 'p')
p.text = 'etree is awesome'

ET.SubElement(body, 'br')

script = ET.SubElement(body, 'script')
script.text = ' document.getElementById("some").innerHTML = "Hello JavaScript!";'

observed = serialize(html, method='html', pretty_print=True)
expected = '<html>\n' + \
' <head>\n' + \
' <style>\n' + \
' body {background-color: white;}\n' + \
' h1 {color: blue;}\n' + \
' p {color: red;}\n' + \
' </style>\n' + \
' </head>\n' + \
' <body>\n' + \
' <p>etree is awesome</p>\n' + \
' <br>\n' + \
' <script> document.getElementById("some").innerHTML = "Hello JavaScript!";</script>\n' + \
' </body>\n' + \
'</html>'
self.assertEqual(observed, expected)

class XMLPullParserTest(unittest.TestCase):

Expand Down
32 changes: 30 additions & 2 deletions Lib/xml/etree/ElementTree.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,21 @@ def _setroot(self, element):
# assert iselement(element)
self._root = element

def _indent(self, elem, level=0):
ind_text = "\n" + level * " "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = ind_text + " "
for e in elem:
self._indent(e, level+1)
if not e.tail or not e.tail.strip():
e.tail = ind_text + " "
if not e.tail or not e.tail.strip():
e.tail = ind_text
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = ind_text

def parse(self, source, parser=None):
"""Load external XML document into element tree.

Expand Down Expand Up @@ -721,6 +736,7 @@ def write(self, file_or_filename,
xml_declaration=None,
default_namespace=None,
method=None, *,
pretty_print=False,
short_empty_elements=True):
"""Write element tree to a file as XML.

Expand All @@ -738,6 +754,9 @@ def write(self, file_or_filename,

*method* -- either "xml" (default), "html, "text", or "c14n"

*pretty_print* -- bool indicating whether the output should be
pretty printed

*short_empty_elements* -- controls the formatting of elements
that contain no content. If True (default)
they are emitted as a single self-closed
Expand All @@ -755,6 +774,10 @@ def write(self, file_or_filename,
else:
encoding = "us-ascii"
enc_lower = encoding.lower()

if pretty_print:
self._indent(self._root)

scoder Aug 25, 2018 •
edited
Loading

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Sorry, but write() is an output method. It shouldn't have side-effects that change the tree.
Just imagine you'd print or log the tree for debugging purposes and it would alter the serialised result later on.


with _get_writer(file_or_filename, enc_lower) as write:
if method == "xml" and (xml_declaration or
(xml_declaration is None and
Expand Down Expand Up @@ -1116,7 +1139,7 @@ def _escape_attrib_html(text):
# --------------------------------------------------------------------

def tostring(element, encoding=None, method=None, *,
short_empty_elements=True):
pretty_print=False, short_empty_elements=True):
"""Generate string representation of XML element.

All subelements are included. If encoding is "unicode", a string
Expand All @@ -1126,11 +1149,15 @@ def tostring(element, encoding=None, method=None, *,
encoding defaulting to US-ASCII, *method* is an optional output which can
be one of "xml" (default), "html", "text" or "c14n".

*pretty_print* is a bool indicating whether the output should be
pretty printed for human reading.

Returns an (optionally) encoded string containing the XML data.

"""
stream = io.StringIO() if encoding == 'unicode' else io.BytesIO()
ElementTree(element).write(stream, encoding, method=method,
pretty_print=pretty_print,
short_empty_elements=short_empty_elements)
return stream.getvalue()

Expand All @@ -1152,10 +1179,11 @@ def tell(self):
return len(self.lst)

def tostringlist(element, encoding=None, method=None, *,
short_empty_elements=True):
pretty_print=False, short_empty_elements=True):
lst = []
stream = _ListDataStream(lst)
ElementTree(element).write(stream, encoding, method=method,
pretty_print=pretty_print,
short_empty_elements=short_empty_elements)
return lst

Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
``ElementTree`` output methods now have ``pretty_print`` (defaulting to
``False``) parameter which leads to output being indented for the human
consumption.

Back | FazBrowse Home | New Git URL