简体   繁体   中英

Python ElementTree: Error Trying to implement a pretty-print

I have some python xml code using ElementTree that writes a very ugly xml file. I wanted to make the xml file a bit more readable. But ElementTree has no pretty-print function. In the documentation ElementTree shows an 'indent' method. When I try to use this indent method, I get the following error.

   Traceback (most recent call last):
      File "/cygdrive/c/data/path/myFile.py", line 756, in <module>
          main()
          ...
          self.writeXML()
          File "/cygdrive/c/data/path/myFile.py", line 248, in writeXML
                self.indent(root)
     File "/cygdrive/c/data/path/myFile.py", line 252, in indent

        i = "\n" + level*"  "
        TypeError: object cannot be interpreted as an index


 def writeXML(self):
   root = self.myTree.getroot()
   self.indent(root)
   self.myTree.write(self.myXML)

 def indent(elem, level=0):
     i = "\n" + level*"  "   #Error Here!!
     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

Am I using indent incorrectly? Or is there an error in this code? Any recommendations for an easier pretty-print?

History: I used to use PyXML which had a pretty-print. But, PyXML is died when I went to python 2.6. lxml has a pretty-print but will not install on my system. So I converted all my code to use ElementTree because I know it works and has most of the basic functionality I need.

You say

i = "\n" + level*"  "
TypeError: object cannot be interpreted as an index

but there is nothing in that statement that looks even vaguely like an index operation. Suggestion: without changing your code in any other way, insert

print repr(elem), repr(level)

before the above statement and edit your question to show the result. Also add what version of Python, and show how you imported ElementTree (or cElementTree).

You appear to have copy/pasted a routine from the effbot's ElementLib ... It looks OK apart from the obfuscatory but not fatal for elem in elem .

One major problem is that for some strange reason you have made it a method of your class instead of a stand-alone function. Either (1) drag it out of your class and call it like

indent(root)

or (2) change its definition to

def indent(self, elem, level=0)

and see if the problem goes away.

Update The problem will go away:

[Python 2.6.6]
>>> import xml.etree.ElementTree as et
>>> et.Element('atag') * "   "
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object cannot be interpreted as an index

The above mysterious error message must have been a bug; Python 2.7.1 produces the much more sensible

TypeError: can't multiply sequence by non-int of type 'Element'

from the same code.

Because you have put this inside a class

    def indent(elem, level=0):
        i = "\n" + level*"  "   #Error Here!!

I would expect that elem is the instance (remember usually we put self here)
and level is actually the elem you are trying to pass in

This means that trying to multiply an element by a string is throwing the TypeError which I think is plausible.

As John Machin says, pull this code out of the class and leave it as a standalone function and you should have more luck

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM