py2xml.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. # Copied from http://code.activestate.com/recipes/577268-python-data-structure-to-xml-serialization/
  2. # - indent feature and better formatting added
  3. # - fixed handling of lists in lists
  4. # - fixed root object name for dictionaries
  5. INDENT_SPACE_SYMBOL = " "
  6. '''
  7. Py2XML - Python to XML serialization
  8. This code transforms a Python data structures into an XML document
  9. Usage:
  10. serializer = Py2XML()
  11. xml_string = serializer.parse( python_object )
  12. print python_object
  13. print xml_string
  14. '''
  15. class Py2XML():
  16. def __init__( self ):
  17. self.data = "" # where we store the processed XML string
  18. def parse( self, pythonObj, objName=None, indent = 0 ):
  19. '''
  20. processes Python data structure into XML string
  21. needs objName if pythonObj is a List
  22. '''
  23. if pythonObj == None:
  24. return "\n" + (INDENT_SPACE_SYMBOL * indent) + ""
  25. if isinstance( pythonObj, dict ):
  26. self.data = self._PyDict2XML( pythonObj, objName, indent=indent+1 )
  27. elif isinstance( pythonObj, list ):
  28. # we need name for List object
  29. self.data = self._PyList2XML( pythonObj, objName, indent=indent+1 )
  30. else:
  31. self.data = "\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s>%(o)s</%(n)s>" % { 'n':objName, 'o':str( pythonObj ) }
  32. return self.data
  33. def _PyDict2XML( self, pyDictObj, objName=None, indent = 0 ):
  34. '''
  35. process Python Dict objects
  36. They can store XML attributes and/or children
  37. '''
  38. tagStr = "" # XML string for this level
  39. attributes = {} # attribute key/value pairs
  40. attrStr = "" # attribute string of this level
  41. childStr = "" # XML string of this level's children
  42. for k, v in pyDictObj.items():
  43. if isinstance( v, dict ):
  44. # child tags, with attributes
  45. childStr += self._PyDict2XML( v, k, indent=indent+1 )
  46. elif isinstance( v, list ):
  47. # child tags, list of children
  48. childStr += self._PyList2XML( v, k, indent=indent+1 )
  49. else:
  50. # tag could have many attributes, let's save until later
  51. attributes.update( { k:v } )
  52. if objName == None:
  53. return childStr
  54. # create XML string for attributes
  55. for k, v in attributes.items():
  56. attrStr += " %s=\"%s\"" % ( k, v )
  57. # let's assemble our tag string
  58. if childStr == "":
  59. tagStr += "\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s%(a)s />" % { 'n':objName, 'a':attrStr }
  60. else:
  61. tagStr += ("\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s%(a)s>%(c)s" + "\n" + (INDENT_SPACE_SYMBOL * indent) + "</%(n)s>") % { 'n':objName, 'a':attrStr, 'c':childStr }
  62. return tagStr
  63. def _PyList2XML( self, pyListObj, objName=None, indent = 0 ):
  64. '''
  65. process Python List objects
  66. They have no attributes, just children
  67. Lists only hold Dicts or Strings
  68. '''
  69. tagStr = "" # XML string for this level
  70. childStr = "" # XML string of children
  71. for childObj in pyListObj:
  72. if isinstance( childObj, dict ):
  73. # here's some Magic
  74. # we're assuming that List parent has a plural name of child:
  75. # eg, persons > person, so cut off last char
  76. # name-wise, only really works for one level, however
  77. # in practice, this is probably ok
  78. childStr += self._PyDict2XML( childObj, objName[:-1], indent=indent+1 )
  79. elif isinstance( childObj, list ):
  80. # here's some Magic
  81. # we're assuming that List parent has a plural name of child:
  82. # eg, persons > person, so cut off last char
  83. # name-wise, only really works for one level, however
  84. # in practice, this is probably ok
  85. childStr += self._PyList2XML( childObj, objName[:-1], indent=indent+1 )
  86. pass
  87. else:
  88. childStr += "\n" + (INDENT_SPACE_SYMBOL * (indent + 1)) + "<" + objName[:-1] + ">"
  89. for string in childObj:
  90. childStr += string;
  91. childStr += "</" + objName[:-1] + ">"
  92. if objName == None:
  93. return childStr
  94. tagStr += ("\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s>%(c)s" + "\n" + (INDENT_SPACE_SYMBOL * indent) + "</%(n)s>") % { 'n':objName, 'c':childStr }
  95. return tagStr