Pretty print XML trees in python

Hello Folks,

today I would like to share with you some python knowledge. I am fiddeling around with python and xml to generate HTTP Post messages. In this blog entry I describe in a brief way how you can create a xml structure and pretty print it.

I am using ElementTree, which does not support pretty printing using the pprint library. To circumvent this, I found this helpful webpage: http://effbot.org/zone/element-lib.htm#prettyprint

Now I would like to share some sample code to illustrate how you can use this function to make you xml look nice:

from xml.etree import ElementTree as ET
'''
copy and paste from http://effbot.org/zone/element-lib.htm#prettyprint
it basically walks your tree and adds spaces and newlines so the tree is
printed in a nice way
'''
def indent(elem, level=0):
  i = "\n" + level*"  "
  if len(elem):
    if not elem.text or not elem.text.strip():
      elem.text = i + "  "
    if not elem.tail or not elem.tail.strip():
      elem.tail = i
    for elem in elem:
      indent(elem, level+1)
    if not elem.tail or not elem.tail.strip():
      elem.tail = i
  else:
    if level and (not elem.tail or not elem.tail.strip()):
      elem.tail = i

'''
function to build an example tree containing cars and ships
vehicles is the root node
'''
def buildTree():
  vehicles = ET.Element("vehicles")

  cars = ET.SubElement(vehicles, "cars")
  cars.set("Type", "American")

  car1 = ET.SubElement(cars, "car")
  car1.text = "Ford Mustang"

  car2 = ET.SubElement(cars, "car")
  car2.text = "Dodge Viper"

  ships = ET.SubElement(vehicles, "ships")
  ships.set("Type", "sunken")

  ship1 = ET.SubElement(ships, "ship")
  ship1.text = "Titanic"

  indent(vehicles)

  tree = ET.ElementTree(vehicles)

  tree.write("vehicle_file.xml", xml_declaration=True, encoding='utf-8', method="xml")

'''
main function, so this program can be called by python program.py
'''
if __name__ == "__main__":
  buildTree()

Copy this source code to a new file “programm.py”. Open a terminal and run it with “python program.py“. The resulting file looks like this.

<?xml version='1.0' encoding='utf-8'?>
<vehicles>
  <cars Type="American">
    <car>Ford Mustang</car>
    <car>Dodge Viper</car>
  </cars>
  <ships Type="sunken">
    <ship>Titanic</ship>
  </ships>
</vehicles>

For more information about using ElementTree, please have a look at the official documentation: http://docs.python.org/2/library/xml.etree.elementtree.html I hope this is helpful, please comment.
Cheers
norbert

Advertisements

6 thoughts on “Pretty print XML trees in python

  1. Hey,

    Using python 2.6.6 on CentOS 6.5
    Trying your code, but getting this output:
    Any suggestions?

    [root@81builder workspace]# ./test.py
    Traceback (most recent call last):
    File “./test.py”, line 56, in
    buildTree()
    File “./test.py”, line 50, in buildTree
    tree.write(“vehicle_file.xml”, xml_declaration=True, encoding=’utf-8′, method=”xml”)
    TypeError: write() got an unexpected keyword argument ‘xml_declaration’

    Thanks!
    Gil

    • Hi there,
      I think you should execute the code using “python test.py”, since the provided code is no shell script. In order to get it working like you suggested (./test.py) you have to provide the python interpreter in the very first line of the code (#! /usr/bin/env python) and make the script executable in your shell (chmod +x test.py)

  2. This was very helpful – for those pep 8 lovers out there – here is Norbert’s indent with pep8 and more python3 friendly. I show the modifications in #.

    def xmlindent(elem, level=0):
    ”’ XML indent : modified from norwied ”’

    pad = ” ”
    i = “\n{}”.format(pad * level)
    #i = “\n” + level*” ”
    if len(elem):
    if not elem.text or not elem.text.strip():
    elem.text = “{} “.format(i)
    #elem.text = i + ” ”
    if not elem.tail or not elem.tail.strip():
    elem.tail = i
    for elem in elem:
    xmlindent(elem, level + 1)
    if not elem.tail or not elem.tail.strip():
    elem.tail = i
    else:
    if level and (not elem.tail or not elem.tail.strip()):
    elem.tail = i

    usage would be something like

    E = xml.etree.ElementTree.Element(‘root’)
    S = xml.etree.ElementTree.SubElement(‘kid’)
    S.set(‘attrib’, ‘value of attribute’)
    xmlindent(E)
    T = xml.etree.ElementTree.ElementTree(E)
    T.write(‘/file.name’,…)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s