# -*- coding: iso-8859-1 -*- """ MoinMoin - XML Serialization @copyright: 2002 by Jürgen Hermann @license: GNU GPL, see COPYING for details. """ import types class Marshal: """ Serialize Python data structures to XML. XML_DECL is the standard XML declaration. The class attributes ROOT_CONTAINER (default "data") and ITEM_CONTAINER (default "item") can be overwritten by derived classes; if ROOT_CONTAINER is `None`, the usually generated container element is omitted, the same is true for ITEM_CONTAINER. PRIVATE_PREFIXES is a list of prefixes of tagnames that are treated as private, i.e. things that should not be serialized. Default is to omit all properties starting with an underscore. TAG_MAP is a translation table for tag names, and is empty by default. It can also be used to surpress certain properties by mapping a tag name to `None`. """ # Convenience: Standard-XML-Deklaration XML_DECL = '\n' # Container Tags ROOT_CONTAINER = "data" ITEM_CONTAINER = "item" # List of private prefixes PRIVATE_PREFIXES = ['_'] # Translation map TAG_MAP = {} def __toXML(self, element, data): """ Recursive helper method that transforms an object to XML. Returns a list of strings, which constitute the XML document. """ # map tag names if self.TAG_MAP: element = self.TAG_MAP.get(element, element) if element: for prefix in self.PRIVATE_PREFIXES: if element.startswith(prefix): return '' content = ['<%s>' % element] else: content = [] # Handle the different data types add_content = content.extend if data is None: content = "" elif isinstance(data, types.StringType): # String content = (data.replace("&", "&") # Must be done first! .replace("<", "<") .replace(">", ">")) elif isinstance(data, types.DictionaryType): # Dictionary for key, value in data.items(): add_content(self.__toXML(key, value)) elif isinstance(data, types.ListType) or isinstance(data, types.TupleType): # List or Tuple for item in data: add_content(self.__toXML(self.ITEM_CONTAINER, item)) elif hasattr(data, "toXML"): add_content([data.toXML()]) elif hasattr(data, "__dict__"): add_content(self.__toXML(self.ROOT_CONTAINER, data.__dict__)) else: # Everything else content = (str(data).replace("&", "&") # Must be done first! .replace("<", "<") .replace(">", ">")) # Close container element if isinstance(content, types.StringType): # No Whitespace if element: content = ['<%s>%s' % (element, content, element)] else: content = [content] elif element: # Whitespace content.append('' % element) return content def toXML(self): """ Transform an instance to an XML string. """ return '\n'.join(self.__toXML(self.ROOT_CONTAINER, self.__dict__))