X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1f780e48af479e7bf9a07eaaa1ab6b41f1ffb17b..ce71cac3dd9a848bb250dfddda5a54de14441db4:/wxPython/samples/ide/activegrid/util/xmlmarshaller.py?ds=inline diff --git a/wxPython/samples/ide/activegrid/util/xmlmarshaller.py b/wxPython/samples/ide/activegrid/util/xmlmarshaller.py index f305f0ada8..1b9cd67d45 100644 --- a/wxPython/samples/ide/activegrid/util/xmlmarshaller.py +++ b/wxPython/samples/ide/activegrid/util/xmlmarshaller.py @@ -9,14 +9,17 @@ # Copyright: (c) 2004-2005 ActiveGrid, Inc. # License: wxWindows License #---------------------------------------------------------------------------- -from activegrid import util -import inspect +import __builtin__ +import sys from types import * import xml.sax import xml.sax.handler -import __builtin__ from xml.sax import saxutils +import objutils + +MODULE_PATH = "__main__" + ### ToDO remove maxOccurs "unbounded" resolves to -1 hacks after bug 177 is fixed """ @@ -86,6 +89,13 @@ a list of the Python attribute names. e.g.: __xmlattrnamespaces__ = { "ag":["firstName", "lastName", "addressLine1", "city"] } +name: __xmlattrgroups__ +type: dict +description: a dict specifying groups of attributes to be wrapped in an enclosing tag. +The key is the name of the enclosing tag; the value is a list of attributes to include +within it. e.g. + +__xmlattrgroups__ = {"name": ["firstName", "lastName"], "address": ["addressLine1", "city", "state", "zip"]} """ @@ -132,23 +142,13 @@ XMLNS_PREFIX = XMLNS + ':' XMLNS_PREFIX_LENGTH = len(XMLNS_PREFIX) BASETYPE_ELEMENT_NAME = 'item' + +# This list doesn't seem to be used. +# Internal documentation or useless? You make the call! MEMBERS_TO_SKIP = ('__module__', '__doc__', '__xmlname__', '__xmlattributes__', '__xmlexclude__', '__xmlflattensequence__', '__xmlnamespaces__', - '__xmldefaultnamespace__', '__xmlattrnamespaces__') - -WELL_KNOWN_OBJECTS = { "xs:element" : "activegrid.model.schema.XsdElement", - "xs:complexType" : "activegrid.model.schema.XsdComplexType", - "xs:complexType" : "activegrid.model.schema.XsdComplexType", - "xs:element" : "activegrid.model.schema.XsdElement", - "xs:key" : "activegrid.model.schema.XsdKey", - "xs:field" : "activegrid.model.schema.XsdKeyField", - "xs:keyref" : "activegrid.model.schema.XsdKeyRef", - "xs:selector" : "activegrid.model.schema.XsdKeySelector", - "xs:schema" : "activegrid.model.schema.Schema", - "ag:schemaOptions":"activegrid.model.schema.SchemaOptions", - "ag:debug" : "activegrid.model.processmodel.DebugOperation", - } - + '__xmldefaultnamespace__', '__xmlattrnamespaces__', + '__xmlattrgroups__') ################################################################################ # @@ -157,47 +157,46 @@ WELL_KNOWN_OBJECTS = { "xs:element" : "activegrid.model.schema.XsdElement", ################################################################################ def _objectfactory(objname, objargs=None, xsname=None): - try: - '''dynamically create an object based on the objname and return - it. look it up in the BASETYPE_ELEMENT_MAP first. - ''' -## print "_objectfactory creating an object of type %s and value %s, xsname=%s" % (objname, objargs, xsname) - # split the objname into the typename and module path, - # importing the module if need be. - if not isinstance(objargs, list): - objargs = [objargs] + '''dynamically create an object based on the objname and return + it. look it up in the BASETYPE_ELEMENT_MAP first. + ''' + # split the objname into the typename and module path, + # importing the module if need be. + if not isinstance(objargs, list): + objargs = [objargs] - if (xsname): - try: - objname = WELL_KNOWN_OBJECTS[xsname] - except KeyError: - pass - - objtype = objname.split('.')[-1] - pathlist = objname.split('.') - modulename = '.'.join(pathlist[0:-1]) - -## print "[objectfactory] objtype is %s" % objtype -## print "[objectfactory] objargs is %s" % `objargs` - - ## since the bool constructor will turn a string of non-zero - ## length into True, we call it with no argument (yielding a - ## False) if the string contains 'false' - if objtype == 'bool' and objargs[0].lower() == 'false': - objargs = None - -## if objtype == 'str': -## print type(objargs) -## print "string we're unescaping: '%s'" % objargs[0] -## objargs = saxutils.unescape(objargs[0]) - if objtype in ('float', 'int', 'str', 'long'): + if (xsname): + try: + objname = knownGlobalTypes[xsname] + except KeyError: + pass + +## print "[objectfactory] creating an object of type %s and value %s, xsname=%s" % (objname, objargs, xsname) + objtype = objname.split('.')[-1] + pathlist = objname.split('.') + modulename = '.'.join(pathlist[0:-1]) + +## print "[objectfactory] object [%s] %s(%r)" % (objname, objtype, objargs) + if objname == 'bool': + return not objargs[0].lower() == 'false' + elif objname == 'str': # don't strip strings - blanks are significant !!! + if len(objargs) > 0: + return saxutils.unescape(objargs[0]).encode() + else: + return '' + elif objname == 'unicode': # don't strip strings - blanks are significant !!! + if len(objargs) > 0: + return saxutils.unescape(objargs[0]).encode() + else: + return '' + elif objtype in ('float', 'int', 'str', 'long'): objargs = [x.strip() for x in objargs] - if objtype == 'str': - objargs = [saxutils.unescape(x) for x in objargs] - + try: if __builtin__.__dict__.has_key(objname): module = __builtin__ + elif knownGlobalModule: + module = knownGlobalModule else: if modulename: module = __import__(modulename) @@ -223,6 +222,13 @@ class Element: return self.attrs.getValue('objtype') else: return 'str' + def toString(self): + print " name = ", self.name, "; attrs = ", self.attrs, "number of children = ", len(self.children) + i = -1 + for child in self.children: + i = i + 1 + childClass = child.__class__.__name__ + print " Child ", i, " class: ",childClass class XMLObjectFactory(xml.sax.ContentHandler): @@ -231,8 +237,23 @@ class XMLObjectFactory(xml.sax.ContentHandler): self.elementstack = [] xml.sax.handler.ContentHandler.__init__(self) + def toString(self): + print "-----XMLObjectFactory Dump-------------------------------" + if (self.rootelement == None): + print "rootelement is None" + else: + print "rootelement is an object" + i = -1 + print "length of elementstack is: ", len(self.elementstack) + for e in self.elementstack: + i = i + 1 + print "elementstack[", i, "]: " + e.toString() + print "-----end XMLObjectFactory--------------------------------" + ## ContentHandler methods def startElement(self, name, attrs): +## print "startElement for name: ", name if name.find(':') > -1: # Strip namespace prefixes for now until actually looking them up in xsd name = name[name.index(':') + 1:] ## for attrname in attrs.getNames(): @@ -251,22 +272,43 @@ class XMLObjectFactory(xml.sax.ContentHandler): xsname = name if name.find(':') > -1: # Strip namespace prefixes for now until actually looking them up in xsd name = name[name.index(':') + 1:] + oldChildren = self.elementstack[-1].children element = self.elementstack.pop() + if ((len(self.elementstack) > 1) and (self.elementstack[-1].getobjtype() == "None")): + parentElement = self.elementstack[-2] +## print "[endElement] %s: found parent with objtype==None: using its grandparent" % name + elif (len(self.elementstack) > 0): + parentElement = self.elementstack[-1] objtype = element.getobjtype() +## print "element objtype is: ", objtype + if (objtype == "None"): +## print "[endElement] %s: skipping a (objtype==None) end tag" % name + return constructorarglist = [] if element.content: strippedElementContent = element.content.strip() if strippedElementContent: constructorarglist.append(element.content) +## print "[endElement] calling objectfactory" obj = _objectfactory(objtype, constructorarglist, xsname) complexType = None if hasattr(obj, '__xsdcomplextype__'): complexType = getattr(obj, '__xsdcomplextype__') + if (hasattr(obj, '__xmlname__') and getattr(obj, '__xmlname__') == "sequence"): +## print "[endElement] sequence found" +## self.toString() + self.elementstack[-1].children = oldChildren +## self.toString() +## print "done moving sequence stuff; returning" + return if len(self.elementstack) > 0: - self.elementstack[-1].children.append((name, obj)) +## print "[endElement] appending child with name: ", name, "; objtype: ", objtype + parentElement.children.append((name, obj)) +## print "parentElement now has ", len(parentElement.children), " children" else: self.rootelement = obj if element.attrs and not isinstance(obj, list): +## print "[endElement] %s: element has attrs and the obj is not a list" % name for attrname, attr in element.attrs.items(): if attrname == XMLNS or attrname.startswith(XMLNS_PREFIX): if attrname.startswith(XMLNS_PREFIX): @@ -293,33 +335,47 @@ class XMLObjectFactory(xml.sax.ContentHandler): if attrname == "maxOccurs" and attr == "unbounded": attr = "-1" attr = _objectfactory(type, attr) - util.setattrignorecase(obj, _toAttrName(obj, attrname), attr) + objutils.setattrignorecase(obj, _toAttrName(obj, attrname), attr) ## obj.__dict__[_toAttrName(obj, attrname)] = attr # stuff any child attributes meant to be in a sequence via the __xmlflattensequence__ flattenDict = {} if hasattr(obj, '__xmlflattensequence__'): - for sequencename, xmlnametuple in obj.__xmlflattensequence__.items(): - for xmlname in xmlnametuple: - flattenDict[xmlname] = sequencename +## print "[endElement] %s: obj has __xmlflattensequence__" % name + if (isinstance(obj.__xmlflattensequence__,dict)): +## print "[endElement] dict with obj.__xmlflattensequence__.items: ", obj.__xmlflattensequence__.items() + for sequencename, xmlnametuple in obj.__xmlflattensequence__.items(): + for xmlname in xmlnametuple: +## print "[endElement]: adding flattenDict[%s] = %s" % (xmlname, sequencename) + flattenDict[xmlname] = sequencename + # handle __xmlflattensequence__ list/tuple (i.e. no element rename) + elif (isinstance(obj.__xmlflattensequence__,list) or isinstance(obj.__xmlflattensequence__,tuple)): + for sequencename in obj.__xmlflattensequence__: + flattenDict[sequencename] = sequencename + else: + raise "Invalid type for __xmlflattensequence___ : it must be a dict, list, or tuple" # reattach an object's attributes to it for childname, child in element.children: +## print "[endElement] childname is: ", childname, "; child is: ", child if flattenDict.has_key(childname): sequencename = _toAttrName(obj, flattenDict[childname]) +## print "[endElement] sequencename is: ", sequencename try: +## print "[endElement] obj.__dict__ is: ", obj.__dict__ sequencevalue = obj.__dict__[sequencename] - except AttributeError: + except (AttributeError, KeyError): sequencevalue = None if sequencevalue == None: sequencevalue = [] obj.__dict__[sequencename] = sequencevalue sequencevalue.append(child) elif isinstance(obj, list): +## print "appended childname = ", childname obj.append(child) else: ## print "childname = %s, obj = %s, child = %s" % (childname, repr(obj), repr(child)) - util.setattrignorecase(obj, _toAttrName(obj, childname), child) -## obj.__dict__[_toAttrName(obj, childname)] = child + objutils.setattrignorecase(obj, _toAttrName(obj, childname), child) + obj.__dict__[_toAttrName(obj, childname)] = child if complexType: for element in complexType.elements: @@ -356,6 +412,11 @@ __typeMappingXsdToPython = { "bool": "bool", "str": "str", "unicode": "unicode", + "short": "int", + "duration": "str", # see above (date) + "datetime": "str", # see above (date) + "time": "str", # see above (date) + "double": "float", } def xsdToPythonType(xsdType): @@ -367,16 +428,34 @@ def xsdToPythonType(xsdType): def _getXmlValue(pythonValue): if (isinstance(pythonValue, bool)): return str(pythonValue).lower() + elif (isinstance(pythonValue, unicode)): + return pythonValue.encode() else: return str(pythonValue) -def unmarshal(xmlstr): +def unmarshal(xmlstr, knownTypes=None, knownModule=None): + global knownGlobalTypes, knownGlobalModule + if (knownTypes == None): + knownGlobalTypes = {} + else: + knownGlobalTypes = knownTypes + knownGlobalModule = knownModule objectfactory = XMLObjectFactory() xml.sax.parseString(xmlstr, objectfactory) return objectfactory.getRootObject() -def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPrint=False, indent=0): +def marshal(obj, elementName=None, prettyPrint=False, indent=0, knownTypes=None, withEncoding=True, encoding=None): + xmlstr = ''.join(_marshal(obj, elementName, prettyPrint=prettyPrint, indent=indent, knownTypes=knownTypes)) + if withEncoding: + if encoding is None: + return '\n%s' % (sys.getdefaultencoding(), xmlstr) + else: + return '\n%s' % (encoding, xmlstr.encode(encoding)) + else: + return xmlstr + +def _marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPrint=False, indent=0, knownTypes=None): if prettyPrint or indent: prefix = ' '*indent newline = '\n' @@ -391,6 +470,8 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr ## attribute, else use the default generic BASETYPE_ELEMENT_NAME. if not nameSpaces: nameSpaces = {} # Need to do this since if the {} is a default parameter it gets shared by all calls into the function nameSpaceAttrs = '' + if knownTypes == None: + knownTypes = {} if hasattr(obj, '__xmlnamespaces__'): for nameSpaceKey, nameSpaceUrl in getattr(obj, '__xmlnamespaces__').items(): if nameSpaceUrl in nameSpaces: @@ -409,7 +490,7 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr nameSpaceAttrs += ' xmlns:%s="%s" ' % (nameSpaceKey, nameSpaceUrl) nameSpaceAttrs = nameSpaceAttrs.rstrip() if hasattr(obj, '__xmldefaultnamespace__'): - nameSpacePrefix = getattr(obj, '__xmldefaultnamespace__') + ':' + nameSpacePrefix = getattr(obj, '__xmldefaultnamespace__') + ':' if not elementName: if hasattr(obj, '__xmlname__'): elementName = nameSpacePrefix + obj.__xmlname__ @@ -417,17 +498,24 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr elementName = nameSpacePrefix + BASETYPE_ELEMENT_NAME else: elementName = nameSpacePrefix + elementName - + if hasattr(obj, '__xmlsequencer__'): + elementAdd = obj.__xmlsequencer__ + else: + elementAdd = None + +## print "marshal: entered with elementName: ", elementName members_to_skip = [] ## Add more members_to_skip based on ones the user has selected ## via the __xmlexclude__ attribute. if hasattr(obj, '__xmlexclude__'): +## print "marshal: found __xmlexclude__" members_to_skip += list(obj.__xmlexclude__) # Marshal the attributes that are selected to be XML attributes. objattrs = '' className = obj.__class__.__name__ classNamePrefix = "_" + className if hasattr(obj, '__xmlattributes__'): +## print "marshal: found __xmlattributes__" xmlattributes = obj.__xmlattributes__ members_to_skip += xmlattributes for attr in xmlattributes: @@ -436,17 +524,19 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr internalAttrName = classNamePrefix + attr # Fail silently if a python attribute is specified to be # an XML attribute but is missing. +## print "marshal: processing attribute ", internalAttrName try: value = obj.__dict__[internalAttrName] except KeyError: continue ## # But, check and see if it is a property first: -## if (hasPropertyValue(obj, attr)): +## if (objutils.hasPropertyValue(obj, attr)): ## value = getattr(obj, attr) ## else: ## continue xsdElement = None if hasattr(obj, '__xsdcomplextype__'): +## print "marshal: found __xsdcomplextype__" complexType = getattr(obj, '__xsdcomplextype__') xsdElement = complexType.findElement(attr) if xsdElement: @@ -468,8 +558,9 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr attrNameSpacePrefix = '' if hasattr(obj, '__xmlattrnamespaces__'): +## print "marshal: found __xmlattrnamespaces__" for nameSpaceKey, nameSpaceAttributes in getattr(obj, '__xmlattrnamespaces__').items(): - if nameSpaceKey == nameSpacePrefix[:-1]: # Don't need to specify attribute namespace if it is the same as it selement + if nameSpaceKey == nameSpacePrefix[:-1]: # Don't need to specify attribute namespace if it is the same as it's element continue if attr in nameSpaceAttributes: attrNameSpacePrefix = nameSpaceKey + ':' @@ -477,173 +568,172 @@ def marshal(obj, elementName=None, nameSpacePrefix='', nameSpaces=None, prettyPr ## if attr.startswith('_'): ## attr = attr[1:] if (hasattr(obj, "__xmlrename__") and attr in obj.__xmlrename__): +## print "marshal: found __xmlrename__ (and its attribute)" attr = obj.__xmlrename__[attr] objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, value) +## print "marshal: new objattrs is: ", objattrs - objtype = type(obj) if isinstance(obj, NoneType): return '' -# return '%s<%s objtype="None"/>%s' % (prefix, elementName, newline) elif isinstance(obj, bool): - return '%s<%s objtype="bool">%s%s' % (prefix, elementName, obj, elementName, newline) + return ['%s<%s objtype="bool">%s%s' % (prefix, elementName, obj, elementName, newline)] elif isinstance(obj, int): - return '''%s<%s objtype="int">%s%s''' % (prefix, elementName, str(obj), elementName, newline) + return ['''%s<%s objtype="int">%s%s''' % (prefix, elementName, str(obj), elementName, newline)] elif isinstance(obj, long): - return '%s<%s objtype="long">%s%s' % (prefix, elementName, str(obj), elementName, newline) + return ['%s<%s objtype="long">%s%s' % (prefix, elementName, str(obj), elementName, newline)] elif isinstance(obj, float): - return '%s<%s objtype="float">%s%s' % (prefix, elementName, str(obj), elementName, newline) + return ['%s<%s objtype="float">%s%s' % (prefix, elementName, str(obj), elementName, newline)] + elif isinstance(obj, unicode): # have to check before basestring - unicode is instance of base string + return ['''%s<%s>%s%s''' % (prefix, elementName, saxutils.escape(obj.encode()), elementName, newline)] elif isinstance(obj, basestring): - return '''%s<%s>%s%s''' % (prefix, elementName, saxutils.escape(obj), elementName, newline) -## elif isinstance(obj, unicode): -## return '''%s<%s>%s%s''' % (prefix, elementName, obj, elementName, newline) + return ['''%s<%s>%s%s''' % (prefix, elementName, saxutils.escape(obj), elementName, newline)] elif isinstance(obj, list): if len(obj) < 1: return '' - xmlString = '%s<%s objtype="list">%s' % (prefix, elementName, newline) + xmlString = ['%s<%s objtype="list">%s' % (prefix, elementName, newline)] for item in obj: - xmlString += marshal(item, nameSpaces=nameSpaces, indent=indent+increment) - xmlString += '%s%s' % (prefix, elementName, newline) + xmlString.extend(_marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)) + xmlString.append('%s%s' % (prefix, elementName, newline)) return xmlString elif isinstance(obj, tuple): if len(obj) < 1: return '' - xmlString = '%s<%s objtype="list" mutable="false">%s' % (prefix, elementName, newline) + xmlString = ['%s<%s objtype="list" mutable="false">%s' % (prefix, elementName, newline)] for item in obj: - xmlString += marshal(item, nameSpaces=nameSpaces, indent=indent+increment) - xmlString += '%s%s' % (prefix, elementName, newline) + xmlString.extend(_marshal(item, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)) + xmlString.append('%s%s' % (prefix, elementName, newline)) return xmlString elif isinstance(obj, dict): - xmlString = '%s<%s objtype="dict">%s' % (prefix, elementName, newline) + xmlString = ['%s<%s objtype="dict">%s' % (prefix, elementName, newline)] subprefix = prefix + ' '*increment subindent = indent + 2*increment for key, val in obj.iteritems(): - xmlString += "%s%s%s%s%s%s%s%s%s%s" \ - % (subprefix, newline, marshal(key, indent=subindent), subprefix, newline, subprefix, newline, marshal(val, nameSpaces=nameSpaces, indent=subindent), subprefix, newline) - xmlString += '%s%s' % (prefix, elementName, newline) + xmlString.append("%s%s" % (subprefix, newline)) + xmlString.extend(_marshal(key, indent=subindent, knownTypes=knownTypes)) + xmlString.append("%s%s%s%s" % (subprefix, newline, subprefix, newline)) + xmlString.extend(_marshal(val, nameSpaces=nameSpaces, indent=subindent, knownTypes=knownTypes)) + xmlString.append("%s%s" % (subprefix, newline)) + xmlString.append('%s%s' % (prefix, elementName, newline)) return xmlString else: moduleName = obj.__class__.__module__ if (moduleName == "activegrid.model.schema"): - xmlString = '%s<%s%s%s' % (prefix, elementName, nameSpaceAttrs, objattrs) + xmlString = ['%s<%s%s%s' % (prefix, elementName, nameSpaceAttrs, objattrs)] else: - xmlString = '%s<%s%s%s objtype="%s.%s"' % (prefix, elementName, nameSpaceAttrs, objattrs, moduleName, className) - # get the member, value pairs for the object, filtering out - # the types we don't support. - xmlMemberString = '' + # Only add the objtype if the element tag is unknown to us. + try: + objname = knownTypes[elementName] + xmlString = ['%s<%s%s%s' % (prefix, elementName, nameSpaceAttrs, objattrs)] + except KeyError: + xmlString = ['%s<%s%s%s objtype="%s.%s"' % (prefix, elementName, nameSpaceAttrs, objattrs, moduleName, className)] +## print "UnknownTypeException: Unknown type (%s.%s) passed to marshaller" % (moduleName, className) + # get the member, value pairs for the object, filtering out the types we don't support + if (elementAdd != None): + prefix += increment*' ' + indent += increment + + xmlMemberString = [] if hasattr(obj, '__xmlbody__'): - xmlMemberString = getattr(obj, obj.__xmlbody__) + xmlbody = getattr(obj, obj.__xmlbody__) + if xmlbody != None: + xmlMemberString.append(xmlbody) else: entryList = obj.__dict__.items() ## # Add in properties ## for key in obj.__class__.__dict__.iterkeys(): ## if (key not in members_to_skip and key not in obj.__dict__ -## and hasPropertyValue(obj, key)): +## and objutils.hasPropertyValue(obj, key)): ## value = getattr(obj, key) ## entryList.append((key, value)) entryList.sort() - for name, value in entryList: -## # special name handling for private "__*" attributes: -## # remove the _ added by Python -## if name.startswith(classNamePrefix): name = name[len(classNamePrefix):] - if name in members_to_skip: continue - if name.startswith('__') and name.endswith('__'): continue -## idx = name.find('__') -## if idx > 0: -## newName = name[idx+2:] -## if newName: -## name = newName - subElementNameSpacePrefix = nameSpacePrefix - if hasattr(obj, '__xmlattrnamespaces__'): - for nameSpaceKey, nameSpaceValues in getattr(obj, '__xmlattrnamespaces__').items(): - if name in nameSpaceValues: - subElementNameSpacePrefix = nameSpaceKey + ':' - break - # handle sequences listed in __xmlflattensequence__ - # specially: instead of listing the contained items inside - # of a separate list, as god intended, list them inside - # the object containing the sequence. - if hasattr(obj, '__xmlflattensequence__') and name in obj.__xmlflattensequence__ and value: - try: - xmlnametuple = obj.__xmlflattensequence__[name] - xmlname = None - if len(xmlnametuple) == 1: - xmlname = xmlnametuple[0] - except: - xmlname = name -## xmlname = name.lower() - for seqitem in value: - xmlMemberString += marshal(seqitem, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment) - else: - if (hasattr(obj, "__xmlrename__") and name in obj.__xmlrename__): - xmlname = obj.__xmlrename__[name] + if hasattr(obj, '__xmlattrgroups__'): + attrGroups = obj.__xmlattrgroups__ + if (not isinstance(attrGroups,dict)): + raise "__xmlattrgroups__ is not a dict, but must be" + for n in attrGroups: + v = attrGroups[n] + members_to_skip += v + else: + attrGroups = {} + # add the list of all attributes to attrGroups + eList = [] + for x, z in entryList: + eList.append(x) + attrGroups['__nogroup__'] = eList + + for eName in attrGroups: + eList = attrGroups[eName] + if (eName != '__nogroup__'): + prefix += increment*' ' + indent += increment + xmlMemberString.append('%s<%s objtype="None">%s' % (prefix, eName, newline)) + for name in eList: + value = obj.__dict__[name] +## print " ", name, " = ", value +## # special name handling for private "__*" attributes: +## # remove the _ added by Python +## if name.startswith(classNamePrefix): name = name[len(classNamePrefix):] + if eName == '__nogroup__' and name in members_to_skip: continue + if name.startswith('__') and name.endswith('__'): continue +## idx = name.find('__') +## if idx > 0: +## newName = name[idx+2:] +## if newName: +## name = newName +## print "marshal: processing subElement ", name + subElementNameSpacePrefix = nameSpacePrefix + if hasattr(obj, '__xmlattrnamespaces__'): + for nameSpaceKey, nameSpaceValues in getattr(obj, '__xmlattrnamespaces__').items(): + if name in nameSpaceValues: + subElementNameSpacePrefix = nameSpaceKey + ':' + break + # handle sequences listed in __xmlflattensequence__ + # specially: instead of listing the contained items inside + # of a separate list, as god intended, list them inside + # the object containing the sequence. + if hasattr(obj, '__xmlflattensequence__') and name in obj.__xmlflattensequence__ and value: + try: + xmlnametuple = obj.__xmlflattensequence__[name] + xmlname = None + if len(xmlnametuple) == 1: + xmlname = xmlnametuple[0] + except: + xmlname = name +## xmlname = name.lower() + for seqitem in value: + xmlMemberString.extend(_marshal(seqitem, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)) else: - xmlname = name -## xmlname = name.lower() -## # skip -## if xmlname.startswith('_') and not xmlname.startswith('__'): -## xmlname = xmlname[1:] -## if (indent > 30): -## print "getting pretty deep, xmlname = ", xmlname - xmlMemberString += marshal(value, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment) + if (hasattr(obj, "__xmlrename__") and name in obj.__xmlrename__): + xmlname = obj.__xmlrename__[name] + else: + xmlname = name +## if (indent > 30): +## print "getting pretty deep, xmlname = ", xmlname + xmlMemberString.extend(_marshal(value, xmlname, subElementNameSpacePrefix, nameSpaces=nameSpaces, indent=indent+increment, knownTypes=knownTypes)) + if (eName != '__nogroup__'): +## print "marshal: Completing attrGroup ", eName + xmlMemberString.append('%s%s' % (prefix, eName, newline)) + prefix = prefix[:-increment] + indent -= increment + # if we have nested elements, add them here, otherwise close the element tag immediately. - if xmlMemberString: - xmlString += '>' + xmlMemberString = filter(lambda x: len(x)>0, xmlMemberString) + if len(xmlMemberString) > 0: + xmlString.append('>') if hasattr(obj, '__xmlbody__'): - xmlString += xmlMemberString - xmlString += '%s' % (elementName, newline) + xmlString.extend(xmlMemberString) + xmlString.append('%s' % (elementName, newline)) else: - xmlString += newline - xmlString += xmlMemberString - xmlString += '%s%s' % (prefix, elementName, newline) + xmlString.append(newline) + if (elementAdd != None): + xmlString.append('%s<%s>%s' % (prefix, elementAdd, newline)) + xmlString.extend(xmlMemberString) + if (elementAdd != None): + xmlString.append('%s%s' % (prefix, elementAdd, newline)) + prefix = prefix[:-increment] + indent -= increment + xmlString.append('%s%s' % (prefix, elementName, newline)) else: - xmlString = xmlString + '/>%s' % newline + xmlString.append('/>%s' % newline) return xmlString - -# We don't use this anymore but in case we want to get properties this is how -# you do it -def hasPropertyValue(obj, attr): - hasProp = False - try: - prop = obj.__class__.__dict__[attr] - if (isinstance(prop, property)): - hasProp = hasattr(obj, attr) - if (hasProp): - # It's a property and it has a value but sometimes we don't want it. - # If there is a _hasattr method execute it and the - # result will tell us whether to include this value - try: - hasProp = obj._hasattr(attr) - except: - pass - except KeyError: - pass - return hasProp - -if __name__ == '__main__': - from xmlmarshallertests import Person, marshalledint, marshalledlist - - l = [1, 2, 3] - d = {'1': 1, '2': 2} - outerlist = [l] - xmlstr = marshal(d, "d", prettyPrint=True) - print xmlstr - - person = Person() - person.firstName = "Albert" - person.lastName = "Camus" - person.addressLine1 = "23 Absurd St." - person.city = "Ennui" - person.state = "MO" - person.zip = "54321" - person._phoneNumber = "808-303-2323" - person.favoriteWords = ['angst', 'ennui', 'existence'] - person.weight = 150 - - xmlstring = marshal(person, 'person', prettyPrint=True) - print xmlstring - - obj = unmarshal(marshalledlist) - print "obj has type %s and value %s" % (type(obj), str(obj)) - for item in obj: - print "item: %s" % str(item)