py2xml.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #
  2. # Metrix++, Copyright 2009-2013, Metrix++ Project
  3. # Link: http://swi.sourceforge.net
  4. #
  5. # This file is a part of Metrix++ Tool.
  6. #
  7. # Metrix++ is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, version 3 of the License.
  10. #
  11. # Metrix++ is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with Metrix++. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. # Copied from http://code.activestate.com/recipes/577268-python-data-structure-to-xml-serialization/
  20. # - indent feature and better formatting added
  21. # - fixed handling of lists in lists
  22. # - fixed root object name for dictionaries
  23. INDENT_SPACE_SYMBOL = " "
  24. '''
  25. Py2XML - Python to XML serialization
  26. This code transforms a Python data structures into an XML document
  27. Usage:
  28. serializer = Py2XML()
  29. xml_string = serializer.parse( python_object )
  30. print python_object
  31. print xml_string
  32. '''
  33. class Py2XML():
  34. def __init__( self ):
  35. self.data = "" # where we store the processed XML string
  36. def parse( self, pythonObj, objName=None, indent = 0 ):
  37. '''
  38. processes Python data structure into XML string
  39. needs objName if pythonObj is a List
  40. '''
  41. if pythonObj == None:
  42. return "\n" + (INDENT_SPACE_SYMBOL * indent) + ""
  43. if isinstance( pythonObj, dict ):
  44. self.data = self._PyDict2XML( pythonObj, objName, indent=indent+1 )
  45. elif isinstance( pythonObj, list ):
  46. # we need name for List object
  47. self.data = self._PyList2XML( pythonObj, objName, indent=indent+1 )
  48. else:
  49. self.data = "\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s>%(o)s</%(n)s>" % { 'n':objName, 'o':str( pythonObj ) }
  50. return self.data
  51. def _PyDict2XML( self, pyDictObj, objName=None, indent = 0 ):
  52. '''
  53. process Python Dict objects
  54. They can store XML attributes and/or children
  55. '''
  56. tagStr = "" # XML string for this level
  57. attributes = {} # attribute key/value pairs
  58. attrStr = "" # attribute string of this level
  59. childStr = "" # XML string of this level's children
  60. for k, v in pyDictObj.items():
  61. if isinstance( v, dict ):
  62. # child tags, with attributes
  63. childStr += self._PyDict2XML( v, k, indent=indent+1 )
  64. elif isinstance( v, list ):
  65. # child tags, list of children
  66. childStr += self._PyList2XML( v, k, indent=indent+1 )
  67. else:
  68. # tag could have many attributes, let's save until later
  69. attributes.update( { k:v } )
  70. if objName == None:
  71. return childStr
  72. # create XML string for attributes
  73. for k, v in attributes.items():
  74. attrStr += " %s=\"%s\"" % ( k, v )
  75. # let's assemble our tag string
  76. if childStr == "":
  77. tagStr += "\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s%(a)s />" % { 'n':objName, 'a':attrStr }
  78. else:
  79. 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 }
  80. return tagStr
  81. def _PyList2XML( self, pyListObj, objName=None, indent = 0 ):
  82. '''
  83. process Python List objects
  84. They have no attributes, just children
  85. Lists only hold Dicts or Strings
  86. '''
  87. tagStr = "" # XML string for this level
  88. childStr = "" # XML string of children
  89. for childObj in pyListObj:
  90. if isinstance( childObj, dict ):
  91. # here's some Magic
  92. # we're assuming that List parent has a plural name of child:
  93. # eg, persons > person, so cut off last char
  94. # name-wise, only really works for one level, however
  95. # in practice, this is probably ok
  96. childStr += self._PyDict2XML( childObj, objName[:-1], indent=indent+1 )
  97. elif isinstance( childObj, list ):
  98. # here's some Magic
  99. # we're assuming that List parent has a plural name of child:
  100. # eg, persons > person, so cut off last char
  101. # name-wise, only really works for one level, however
  102. # in practice, this is probably ok
  103. childStr += self._PyList2XML( childObj, objName[:-1], indent=indent+1 )
  104. pass
  105. else:
  106. childStr += "\n" + (INDENT_SPACE_SYMBOL * (indent + 1)) + "<" + objName[:-1] + ">"
  107. for string in childObj:
  108. childStr += string;
  109. childStr += "</" + objName[:-1] + ">"
  110. if objName == None:
  111. return childStr
  112. tagStr += ("\n" + (INDENT_SPACE_SYMBOL * indent) + "<%(n)s>%(c)s" + "\n" + (INDENT_SPACE_SYMBOL * indent) + "</%(n)s>") % { 'n':objName, 'c':childStr }
  113. return tagStr