📄 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 standalone
class 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 = False
if 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 + -