comparison MoinMoin/wikixml/marshal.py @ 0:77665d8e2254

tag of nonpublic@localhost--archive/moin--enterprise--1.5--base-0 (automatically generated log message) imported from: moin--main--1.5--base-0
author Thomas Waldmann <tw-public@gmx.de>
date Thu, 22 Sep 2005 15:09:50 +0000
parents
children e80ad5feaba8
comparison
equal deleted inserted replaced
-1:000000000000 0:77665d8e2254
1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - XML Serialization
4
5 @copyright: 2002 by Jürgen Hermann <jh@web.de>
6 @license: GNU GPL, see COPYING for details.
7 """
8
9 import types
10
11
12 class Marshal:
13 """ Serialize Python data structures to XML.
14
15 XML_DECL is the standard XML declaration.
16
17 The class attributes ROOT_CONTAINER (default "data") and
18 ITEM_CONTAINER (default "item") can be overwritten by derived
19 classes; if ROOT_CONTAINER is `None`, the usually generated
20 container element is omitted, the same is true for ITEM_CONTAINER.
21
22 PRIVATE_PREFIXES is a list of prefixes of tagnames that are
23 treated as private, i.e. things that should not be serialized.
24 Default is to omit all properties starting with an underscore.
25
26 TAG_MAP is a translation table for tag names, and is empty by
27 default. It can also be used to surpress certain properties by
28 mapping a tag name to `None`.
29 """
30
31 # Convenience: Standard-XML-Deklaration
32 XML_DECL = '<?xml version="1.0" encoding="ISO-8859-1"?>\n'
33
34 # Container Tags
35 ROOT_CONTAINER = "data"
36 ITEM_CONTAINER = "item"
37
38 # List of private prefixes
39 PRIVATE_PREFIXES = ['_']
40
41 # Translation map
42 TAG_MAP = {}
43
44
45 def __toXML(self, element, data):
46 """ Recursive helper method that transforms an object to XML.
47
48 Returns a list of strings, which constitute the XML document.
49 """
50 # map tag names
51 if self.TAG_MAP:
52 element = self.TAG_MAP.get(element, element)
53
54 if element:
55 for prefix in self.PRIVATE_PREFIXES:
56 if element.startswith(prefix): return ''
57 content = ['<%s>' % element]
58 else:
59 content = []
60
61 # Handle the different data types
62 add_content = content.extend
63
64 if data is None:
65 content = "<none/>"
66
67 elif isinstance(data, types.StringType):
68 # String
69 content = (data.replace("&", "&amp;") # Must be done first!
70 .replace("<", "&lt;")
71 .replace(">", "&gt;"))
72
73 elif isinstance(data, types.DictionaryType):
74 # Dictionary
75 for key, value in data.items():
76 add_content(self.__toXML(key, value))
77
78 elif isinstance(data, types.ListType) or isinstance(data, types.TupleType):
79 # List or Tuple
80 for item in data:
81 add_content(self.__toXML(self.ITEM_CONTAINER, item))
82
83 elif hasattr(data, "toXML"):
84 add_content([data.toXML()])
85
86 elif hasattr(data, "__dict__"):
87 add_content(self.__toXML(self.ROOT_CONTAINER, data.__dict__))
88
89 else:
90 # Everything else
91 content = (str(data).replace("&", "&amp;") # Must be done first!
92 .replace("<", "&lt;")
93 .replace(">", "&gt;"))
94
95 # Close container element
96 if isinstance(content, types.StringType):
97 # No Whitespace
98 if element:
99 content = ['<%s>%s</%s>' % (element, content, element)]
100 else:
101 content = [content]
102 elif element:
103 # Whitespace
104 content.append('</%s>' % element)
105
106 return content
107
108
109 def toXML(self):
110 """ Transform an instance to an XML string.
111 """
112 return '\n'.join(self.__toXML(self.ROOT_CONTAINER, self.__dict__))
113