Friday, November 13, 2009

Python didn’t have it, anyway…

Now, however, it does. Kinda.

def Python_to_XML_String(inst, name):
   builder = "<" + name + ">"
   builder += Python_to_XML_String_Recursion(inst)
   builder += "</" + name + ">"
   return minidom.parseString(builder)
   
def Python_to_XML_String_Recursion(inst):
   # Put entire object inside an elem w/ same name as the class.
   builder = ""
   for attr in inst:
      value = inst[attr]
      if type(value) == types.DictionaryType:
         # Recursively process subobjects
         builder += '<' + attr + '>'
         builder += Python_to_XML_String_Recursion(value)
         builder += '</' + attr + '>'
      elif type(value) == types.ListType:
         builder += '<' + attr + '>'
         for item in value:
            if type(item) == types.DictionaryType:
               builder += '<Item>'
               builder += Python_to_XML_String_Recursion(item)
               builder += '</Item>'
            else:
               builder += '<Item>'
               builder += str(item).replace("&","&amp;").replace("<","&lt;")
               builder += '</Item>'
         builder += '</' + attr + '>'
      else:
         # Convert anything else to string, put it in an element
         builder += '<' + attr + '>'
         builder += str(value).replace("&","&amp;").replace("<","&lt;")
         builder += '</' + attr + '>'
   return builder

(Note: I need a better source colouring plugin for WLW. Anyone know of one?)

This code is pretty limiting:

  • It’ll pretty much only work with generic type objects ({}, [] and primitives), but that’s all I need.
  • It also relies on the str() function to convert everything into a string, with no typing. This means that booleans (True, False) stay capitalised, which could cause some problems if your code is expecting lower-case values, and dates are unformatted.
  • It returns a minidom object (Which, obviously, has to be imported). You can output this with a .toxml() call.
  • It relies on the first object being passed in being a dictionary object, and that there will never be a list inside a list. This could be coded around, but it’ll take more work (and more helper functions, to fill in the “missing” information.
  • It takes an initial “name” argument to define the outer object.

To use it, call it like this:

Python_to_XML_String({'Thing': 'Value', 'Object', ['Thing 1', 'Thing 2']},'MyObject')

And it’ll return (for that example) an XML object looking like this:

<MyObject>
   <Thing>Value</Thing>
   <Object>
      <Item>Thing 1</Item>
      <Item>Thing 2</Item>
   </Object>
</MyObject>

I hope this is helpful to someone else out there…

No comments:

Post a Comment