How to generate XML
Michael Chermside
mcherm at destiny.com
Wed Feb 13 14:35:55 EST 2002
>>> I'm amazed that people always start proposing difficult-to-use
>>> libraries when this question comes up. I'd prefer to use
>>>
>>> print "<foo/>"
>
> For the special case where you have a tree structure whose nodes
> are instances of Python classes, implement an "export" method in
> each class something like the following:
>
> def export(self, outfile, level):
> [...]
I tend to agree with the original poster: simply writing your own print
routines isn't difficult at all. However, if you're going to go around
putting in standard "export()" methods, perhaps you'd prefer something
which does it automatically.
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.
-- Michael Chermside
------------------------ <code> -------------------------
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))
------------------------ </code> -------------------------
More information about the Python-list
mailing list