How to generate XML
Mark McEahern
marklists at mceahern.com
Wed Feb 13 15:50:12 EST 2002
[Michael Chermside]
> The following code will create an xmlPrint() method. Pass it an object,
> and it prints it out in a pseudoreadable fashion. If I were really going
> to be using this, I'd modify _xmlPrintObj() so it checks for a .toXML()
> method and invokes that instead if such a thing exists. But there's no
> reason to write boilerplate in Python, where introspection is so easy.
There seem to be two bugs in the code you posted, Michael. For what it's
worth, here's a fully working demo of the code with the minor bug fixes:
#! /usr/bin/env python
# xmlPrint.py
#
# Code from Michael Chermside's posting to comp.lang.python
#
# http://mail.python.org/pipermail/python-list/2002-February/087283.html
import sys
import types
def xmlPrint(obj, writer=sys.stdout, indentText=' '):
"""Print an object in XML format."""
_xmlPrintObj(obj, _IndentingWriter(writer, indentText))
class _IndentingWriter:
def __init__(self,
writer=sys.stdout,
indentText=' ',
indentLevel=0):
self.writer = writer
self.indentText = indentText
self.indentLevel = indentLevel
self.indentStr = indentText * indentLevel
def incr(self):
return _IndentingWriter(self.writer, self.indentText,
self.indentLevel + 1)
def writeline(self, text):
self.writer.write(self.indentStr)
self.writer.write(text)
self.writer.write('\n')
def _xmlPrintObj(obj, writer):
"""Print an object in XML format (internal interface)."""
# Print tags for the object itself based on class name
tagname = obj.__class__.__name__
writer.writeline('<%s>' % tagname)
# for all fields not beginning with an underscore...
for fieldName in filter(lambda x: x[0]!='_', dir(obj)):
_xmlPrintField(getattr(obj, fieldName), fieldName,
writer.incr())
# close the tags for the object itself
writer.writeline('</%s>' % tagname)
def _xmlPrintField(value, fieldName, writer):
"""Print a field of some object, labled with its fieldName."""
if type(value) == types.InstanceType:
# for sub-objects we print field name then recurse
writer.writeline('<%s>' % fieldName)
_xmlPrintObj(value, writer.incr())
writer.writeline('</%s>' % fieldName)
elif type(value) in (types.ListType, types.TupleType):
# for sequences we print all items
writer.writeline('<%s>' % fieldName)
for v in value:
_xmlPrintField(v, 'value', writer.incr())
writer.writeline('</%s>' % fieldName)
else:
# for all other fields just use str()
writer.writeline('<%s>%s</%s>' % (fieldName, value, fieldName))
if __name__=="__main__":
class Person:pass
p = Person()
p.firstName = "Mark"
p.lastName = "McEahern"
p.favoriteColors = ['blue', 'purple']
xmlPrint(p)
More information about the Python-list
mailing list