📄 xmlmarshaller.py
字号:
## parameter list, look for it in the __xmlname__ attribute, ## else use the default generic BASETYPE_ELEMENT_NAME. nameSpaceAttrs = self.appendNSStack(obj) nameSpacePrefix = self.getNSPrefix() if not elementName: if hasattr(obj, "__xmlname__"): elementName = nameSpacePrefix + obj.__xmlname__ else: elementName = nameSpacePrefix + BASETYPE_ELEMENT_NAME else: elementName = nameSpacePrefix + elementName if (hasattr(obj, "__xmlsequencer__")) and (obj.__xmlsequencer__ != None): if (XMLSCHEMA_XSD_URL in self.nsstack[-1].nameSpaces.values()): for kShort, vLong in self.nsstack[-1].nameSpaces.iteritems(): if vLong == XMLSCHEMA_XSD_URL: if kShort != DEFAULT_NAMESPACE_KEY: xsdPrefix = kShort + ':' else: xsdPrefix = '' break else: xsdPrefix = 'xs:' elementAdd = xsdPrefix + obj.__xmlsequencer__ else: elementAdd = None members_to_skip = [] ## Add more members_to_skip based on ones the user has selected ## via the __xmlexclude__ and __xmldeepexclude__ attributes. members_to_skip.extend(excludeAttrs) # Marshal the attributes that are selected to be XML attributes. objattrs = "" className = ag_className(obj) classNamePrefix = "_" + className if hasattr(obj, "__xmlattributes__"): xmlattributes = obj.__xmlattributes__ members_to_skip.extend(xmlattributes) for attr in xmlattributes: internalAttrName = attr ifDefPy() if (attr.startswith("__") and not attr.endswith("__")): internalAttrName = classNamePrefix + attr endIfDef() # Fail silently if a python attribute is specified to be # an XML attribute but is missing. attrNameSpacePrefix = "" if hasattr(obj, "__xmlattrnamespaces__"): for nameSpaceKey, nameSpaceAttributes in getattr(obj, "__xmlattrnamespaces__").iteritems(): if nameSpaceKey == nameSpacePrefix[:-1]: # Don't need to specify attribute namespace if it is the same as its element continue if attr in nameSpaceAttributes: attrNameSpacePrefix = nameSpaceKey + ":" break attrs = obj.__dict__ value = attrs.get(internalAttrName) if (hasattr(obj, "__xmlrename__") and attr in asDict(obj.__xmlrename__)): attr = obj.__xmlrename__[attr] xsdElement = None complexType = getComplexType(obj) if (complexType != None): xsdElement = complexType.findElement(attr) if (xsdElement != None): default = xsdElement.default if (default != None): if ((default == value) or (default == _getXmlValue(value))): continue else: if (value == None): continue elif xsdElement.type == TYPE_QNAME: value = self.contractQName(value, obj, attr) elif value == None: continue # ToDO remove maxOccurs hack after bug 177 is fixed if attr == "maxOccurs" and value == -1: value = "unbounded" if isinstance(value, bool): if value == True: value = "true" else: value = "false" else: value = objutils.toDiffableRepr(value) objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, utillang.escape(value)) if (obj == None): xmlString = [""] elif isinstance(obj, bool): objTypeStr = self._genObjTypeStr("bool") xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, obj, elementName, newline)] elif isinstance(obj, int): objTypeStr = self._genObjTypeStr("int") xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] elif isinstance(obj, long): objTypeStr = self._genObjTypeStr("long") xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] elif isinstance(obj, float): objTypeStr = self._genObjTypeStr("float") xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] elif isinstance(obj, unicode): # have to check before basestring - unicode is instance of base string xmlString = ['%s<%s>%s</%s>%s' % (prefix, elementName, utillang.escape(obj.encode()), elementName, newline)] elif isinstance(obj, basestring): xmlString = ['%s<%s>%s</%s>%s' % (prefix, elementName, utillang.escape(obj), elementName, newline)] elif isinstance(obj, datetime.datetime): objTypeStr = self._genObjTypeStr("datetime") xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] elif isinstance(obj, datetime.date): objTypeStr = self._genObjTypeStr("date") xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] elif isinstance(obj, datetime.time): objTypeStr = self._genObjTypeStr("time") xmlString = ['%s<%s%s>%s</%s>%s' % (prefix, elementName, objTypeStr, str(obj), elementName, newline)] elif isinstance(obj, list): if len(obj) < 1: xmlString = "" else: objTypeStr = self._genObjTypeStr("list") xmlString = ['%s<%s%s>%s' % (prefix, elementName, objTypeStr, newline)] for item in obj: xmlString.extend(self._marshal(item, indent=indent+increment)) xmlString.append("%s</%s>%s" % (prefix, elementName, newline)) elif isinstance(obj, tuple): if len(obj) < 1: xmlString = "" else: objTypeStr = self._genObjTypeStr("list") xmlString = ['%s<%s%s mutable="false">%s' % (prefix, elementName, objTypeStr, newline)] for item in obj: xmlString.extend(self._marshal(item, indent=indent+increment)) xmlString.append("%s</%s>%s" % (prefix, elementName, newline)) elif isinstance(obj, dict): objTypeStr = self._genObjTypeStr("dict") xmlString = ['%s<%s%s>%s' % (prefix, elementName, objTypeStr, newline)] subprefix = prefix + " "*increment subindent = indent + 2*increment keys = obj.keys() keys.sort() for key in keys: xmlString.append("%s<%s>%s" % (subprefix, DICT_ITEM_NAME, newline)) xmlString.extend(self._marshal(key, elementName=DICT_ITEM_KEY_NAME, indent=subindent)) xmlString.extend(self._marshal(obj[key], elementName=DICT_ITEM_VALUE_NAME, indent=subindent)) xmlString.append("%s</%s>%s" % (subprefix, DICT_ITEM_NAME, newline)) xmlString.append("%s</%s>%s" % (prefix, elementName, newline)) elif hasattr(obj, "__xmlcontent__"): contentValue = getattr(obj, obj.__xmlcontent__) if contentValue == None: xmlString = ["%s<%s%s%s/>%s" % (prefix, elementName, nameSpaceAttrs, objattrs, newline)] else: contentValue = utillang.escape(contentValue) xmlString = ["%s<%s%s%s>%s</%s>%s" % (prefix, elementName, nameSpaceAttrs, objattrs, contentValue, elementName, newline)] else: # Only add the objtype if the element tag is unknown to us. if (isinstance(obj, GenericXMLObject)): objTypeStr = "" elif (self.isKnownType(elementName) == True): objTypeStr = "" else: objTypeStr = self._genObjTypeStr("%s.%s" % (obj.__class__.__module__, className)) xmlString = ['%s<%s%s%s%s' % (prefix, elementName, nameSpaceAttrs, objattrs, objTypeStr)] # 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__"): xmlbody = getattr(obj, obj.__xmlbody__) if xmlbody != None: xmlMemberString.append(utillang.escape(xmlbody)) else: if hasattr(obj, "__xmlattrgroups__"): attrGroups = obj.__xmlattrgroups__.copy() if (not isinstance(attrGroups, dict)): raise "__xmlattrgroups__ is not a dict, but must be" for n in attrGroups.iterkeys(): members_to_skip.extend(attrGroups[n]) else: attrGroups = {} # add the list of all attributes to attrGroups eList = obj.__dict__.keys() eList.sort() attrGroups["__nogroup__"] = eList for eName, eList in attrGroups.iteritems(): if (eName != "__nogroup__"): prefix += increment*" " indent += increment objTypeStr = self._genObjTypeStr("None") xmlMemberString.append('%s<%s%s>%s' % (prefix, eName, objTypeStr, newline)) for name in eList: value = obj.__dict__[name] if eName == "__nogroup__" and name in members_to_skip: continue if name.startswith("__") and name.endswith("__"): continue if (hasattr(obj, "__xmlcdatacontent__") and (obj.__xmlcdatacontent__ == name)): continue subElementNameSpacePrefix = nameSpacePrefix if hasattr(obj, "__xmlattrnamespaces__"): for nameSpaceKey, nameSpaceValues in getattr(obj, "__xmlattrnamespaces__").iteritems(): 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 (value != None) and (name in asDict(obj.__xmlflattensequence__))): xmlnametuple = obj.__xmlflattensequence__[name] if (xmlnametuple == None): xmlnametuple = [name] elif (not isinstance(xmlnametuple, (tuple,list))): xmlnametuple = [str(xmlnametuple)] xmlname = None if (len(xmlnametuple) == 1): xmlname = xmlnametuple[0] if not isinstance(value, (list, tuple)): value = [value] for seqitem in value: xmlMemberString.extend(self._marshal(seqitem, xmlname, subElementNameSpacePrefix, indent=indent+increment)) else: if (hasattr(obj, "__xmlrename__") and name in asDict(obj.__xmlrename__)): xmlname = obj.__xmlrename__[name] else: xmlname = name if (value != None): xmlMemberString.extend(self._marshal(value, xmlname, subElementNameSpacePrefix, indent=indent+increment)) if (eName != "__nogroup__"): xmlMemberString.append("%s</%s>%s" % (prefix, eName, newline)) prefix = prefix[:-increment] indent -= increment # if we have nested elements, add them here, otherwise close the element tag immediately. newList = [] for s in xmlMemberString: if (len(s) > 0): newList.append(s) xmlMemberString = newList if len(xmlMemberString) > 0: xmlString.append(">") if hasattr(obj, "__xmlbody__"): xmlString.extend(xmlMemberString) xmlString.append("</%s>%s" % (elementName, newline)) else: xmlString.append(newline) if (elementAdd != None): xmlString.append("%s<%s>%s" % (prefix, elementAdd, newline)) xmlString.extend(xmlMemberString) if (elementAdd != None): xmlString.append("%s</%s>%s" % (prefix, elementAdd, newline)) prefix = prefix[:-increment] indent -= increment xmlString.append("%s</%s>%s" % (prefix, elementName, newline)) else: if hasattr(obj, "__xmlcdatacontent__"): cdataAttr = obj.__xmlcdatacontent__ cdataContent = obj.__dict__[cdataAttr] xmlString.append("><![CDATA[%s]]></%s>%s" % (cdataContent, elementName, newline)) else: xmlString.append("/>%s" % newline) if aglogging.isEnabledForDebug(xmlMarshallerLogger): aglogging.debug(xmlMarshallerLogger, "<-- _marshal: %s", objutils.toDiffableString(xmlString)) #print "<-- _marshal: %s" % str(xmlString) self.popNSStack() return xmlString# A simple test, to be executed when the xmlmarshaller is run standaloneclass MarshallerPerson: __xmlname__ = "person" __xmlexclude__ = ["fabulousness",] __xmlattributes__ = ("nonSmoker",) __xmlrename__ = {"_phoneNumber": "telephone"} __xmlflattensequence__ = {"favoriteWords": ("vocabulary",)} __xmlattrgroups__ = {"name": ["firstName", "lastName"], "address": ["addressLine1", "city", "state", "zip"]} def setPerson(self): self.firstName = "Albert" self.lastName = "Camus" self.addressLine1 = "23 Absurd St." self.city = "Ennui" self.state = "MO" self.zip = "54321" self._phoneNumber = "808-303-2323" self.favoriteWords = ["angst", "ennui", "existence"] self.phobias = ["war", "tuberculosis", "cars"] self.weight = 150 self.fabulousness = "tres tres" self.nonSmoker = Falseif isMain(__name__): p1 = MarshallerPerson() p1.setPerson() xmlP1 = marshal(p1, prettyPrint=True, encoding="utf-8") print "\n########################" print "# testPerson test case #" print "########################" print xmlP1 p2 = unmarshal(xmlP1) xmlP2 = marshal(p2, prettyPrint=True, encoding="utf-8") if xmlP1 == xmlP2: print "Success: repeated marshalling yields identical results" else: print "Failure: repeated marshalling yields different results" print xmlP2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -