0

I am beginning to use Python to write values to an XML file to be read by a database. To start things off, I used the example in this link:

Pretty print XML trees in python

I used the example script:

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()

intending to get the following in vehicle_file.xml:

<?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>

but I ended up with:

<?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>

Note that the end tags for cars, ships, and vehicles are not dedented as they should be, fouling up the remainder of the xml file.

As a check, I put a debug statement in the indent() function printing out the level and the tag name. I got the correct results:

0 vehicles
1 cars
2 car
2 car
1 ships
2 ship

Why is indent() not dedenting the end tags? Am I missing something in the indent() function? Why are the end tags not dedented? Am I missing a statement in the indent function?

PyNerd
  • 645
  • 2
  • 9
  • 19
  • 3
    You are adding fake spaces to your XML tree to make it pretty print? That sounds like a horrible idea in and of itself. There is a pretty print function already available. – Mad Physicist Jul 14 '17 at 19:45
  • Thank you, Mad Physicist. I eliminated the indent() function and did this instead: `vehicleText = ET.tostring(vehicles)` `xmlText = xml.dom.minidom.parseString(vehicleText)` and `prettyXmlText = xmlText.toprettyxml()`. I got the correct indentation as a result . – PyNerd Jul 14 '17 at 19:59
  • Not only did you get the correct indentation, but you also got the original XML tree back from your function. That can be important sometimes. – Mad Physicist Jul 14 '17 at 20:25

0 Answers0