# Name: xmlmarshaller.py
# Purpose:
#
-# Authors: John Spurling, Joel Hare, Alan Mullendore
+# Authors: John Spurling, Joel Hare, Jeff Norton, Alan Mullendore
#
# Created: 7/28/04
# CVS-ID: $Id$
ifDefPy()
import xml.sax
import xml.sax.handler
+import xml.sax.saxutils
+import datetime
endIfDef()
-import xml.sax.saxutils as saxutils
+import activegrid.util.utillang as utillang
import activegrid.util.objutils as objutils
+import activegrid.util.sysutils as sysutils
import activegrid.util.aglogging as aglogging
MODULE_PATH = "__main__"
## ToDO remove maxOccurs "unbounded" resolves to -1 hacks after bug 177 is fixed
+##unboundedVal = 2147483647 # value used for maxOccurs == "unbounded"
"""
Special attributes that we recognize:
global xmlMarshallerLogger
xmlMarshallerLogger = logging.getLogger("activegrid.util.xmlmarshaller.marshal")
-xmlMarshallerLogger.setLevel(aglogging.LEVEL_WARN)
# INFO : low-level info
# DEBUG : debugging info
################################################################################
def setattrignorecase(object, name, value):
+## print "[setattrignorecase] name = %s, value = %s" % (name, value)
if (name not in object.__dict__):
namelow = name.lower()
for attr in object.__dict__:
object.__dict__[name] = value
def getComplexType(obj):
+ if (hasattr(obj, "_instancexsdcomplextype")):
+ return obj._instancexsdcomplextype
if (hasattr(obj, "__xsdcomplextype__")):
return obj.__xsdcomplextype__
return None
-def _objectfactory(objname, objargs=None, objclass=None):
- "dynamically create an object based on the objname and return it."
-## print "[objectfactory] objname [%s]" % (objname)
+def _objectfactory(objtype, objargs=None, objclass=None):
+ "dynamically create an object based on the objtype and return it."
if not isinstance(objargs, list):
objargs = [objargs]
if (objclass != None):
+ obj = None
if (len(objargs) > 0):
if (hasattr(objclass, "__xmlcdatacontent__")):
obj = objclass()
contentAttr = obj.__xmlcdatacontent__
obj.__dict__[contentAttr] = str(objargs[0])
- return obj
- return objclass(*objargs)
+ else:
+ obj = objclass(*objargs)
else:
- return objclass()
- return objutils.newInstance(objname, objargs)
+ obj = objclass()
+ if ((obj != None) and (hasattr(obj, 'postUnmarshal'))):
+ obj.postUnmarshal()
+ return obj
+ return objutils.newInstance(objtype, objargs)
+
+class GenericXMLObject(object):
+ def __init__(self, content=None):
+ if content != None:
+ self._content = content
+ self.__xmlcontent__ = '_content'
+
+ def __str__(self):
+ return "GenericXMLObject(%s)" % objutils.toDiffableString(self.__dict__)
+ def setXMLAttributes(self, xmlName, attrs=None, children=None, nsMap=None, defaultNS=None):
+ if xmlName != None:
+ i = xmlName.rfind(':')
+ if i < 0:
+ self.__xmlname__ = xmlName
+ if defaultNS != None:
+ self.__xmldefaultnamespace__ = str(defaultNS)
+ else:
+ self.__xmlname__ = xmlName[i+1:]
+ prefix = xmlName[:i]
+ if nsMap.has_key(prefix):
+ self.__xmldefaultnamespace__ = str(nsMap[prefix])
+ if attrs != None:
+ for attrname, attr in attrs.items():
+ attrname = str(attrname)
+ if attrname == XMLNS or attrname.startswith(XMLNS_PREFIX):
+ pass
+ elif attrname == "objtype":
+ pass
+ else:
+ if not hasattr(self, '__xmlattributes__'):
+ self.__xmlattributes__ = []
+ i = attrname.rfind(':')
+ if i >= 0:
+ prefix = attrname[:i]
+ attrname = attrname[i+1:]
+ if not hasattr(self, '__xmlattrnamespaces__'):
+ self.__xmlattrnamespaces__ = {}
+ if self.__xmlattrnamespaces__.has_key(prefix):
+ alist = self.__xmlattrnamespaces__[prefix]
+ else:
+ alist = []
+ alist.append(attrname)
+ self.__xmlattrnamespaces__[prefix] = alist
+ self.__xmlattributes__.append(attrname)
+ if hasattr(self, '__xmlattributes__'):
+ self.__xmlattributes__.sort()
+ if children != None and len(children) > 0:
+ childList = []
+ flattenList = {}
+ for childname, child in children:
+ childstr = str(childname)
+ if childstr in childList:
+ if not flattenList.has_key(childstr):
+ flattenList[childstr] = (childstr,)
+ else:
+ childList.append(childstr)
+ if len(flattenList) > 0:
+ self.__xmlflattensequence__ = flattenList
+
+ def initialize(self, arg1=None):
+ pass
+
+
class Element:
def __init__(self, name, attrs=None, xsname=None):
self.name = name
self.children = []
self.objclass = None
self.xsname = xsname
+ self.objtype = None
def getobjtype(self):
- objtype = self.attrs.get("objtype")
+# objtype = self.attrs.get("objtype")
+ objtype = self.objtype
if (objtype == None):
if (len(self.children) > 0):
objtype = "dict"
self.targetNS = None
self.defaultNS = None
self.prefix = None
-
- def isEmpty(self):
- return ((self.nsMap == {}) and (self.targetNS == None) and (self.defaultNS == None))
+ def __str__(self):
+ if self.prefix == None:
+ strVal = 'prefix = None; '
+ else:
+ strVal = 'prefix = "%s"; ' % (self.prefix)
+ if self.targetNS == None:
+ strVal += 'targetNS = None; '
+ else:
+ strVal += 'targetNS = "%s"; ' % (self.targetNS)
+ if self.defaultNS == None:
+ strVal += 'defaultNS = None; '
+ else:
+ strVal += 'defaultNS = "%s"; ' % (self.defaultNS)
+ if len(self.nsMap) == 0:
+ strVal += 'nsMap = None; '
+ else:
+ strVal += 'nsMap = {'
+ for ik, iv in self.nsMap.iteritems():
+ strVal += '%s=%s; ' % (ik,iv)
+ strVal += '}'
+ return strVal
+
def setKnownTypes(self, masterKnownTypes, masterKnownNamespaces, parentNSE):
# if we're a nested element, extend our parent element's mapping
if parentNSE != None:
self.knownTypes = parentNSE.knownTypes.copy()
# but if we have a different default namespace, replace the parent's default mappings
- if parentNSE.defaultNS != self.defaultNS:
+ if (self.defaultNS != None) and (parentNSE.defaultNS != self.defaultNS):
newKT = self.knownTypes.copy()
for tag in newKT:
if tag.find(':') < 0:
self.knownTypes[knownTagName] = mapClass
else: # e.g. "ItemSearchRequest"
self.knownTypes[tag] = mapClass
-## print 'mapping <%s> to class "%s"' % (tag, mapClass.__name__)
def expandQName(self, eName, attrName, attrValue):
bigValue = attrValue
if shortNs == attrNS:
bigValue = '%s:%s' % (longNs, attrNCName)
break
-## print '[expandQName] input attrName = "%s" and attrValue "%s"; output = "%s"' % (attrName, attrValue, bigValue)
return bigValue
class XMLObjectFactory(xml.sax.ContentHandler):
- def __init__(self, knownTypes=None, knownNamespaces=None):
+ def __init__(self, knownTypes=None, knownNamespaces=None, xmlSource=None, createGenerics=False):
self.rootelement = None
- if (knownTypes == None):
- self.knownTypes = {}
- else:
- self.knownTypes = knownTypes
- if (knownNamespaces == None):
- self.knownNamespaces = {}
+ if xmlSource == None:
+ self.xmlSource = "unknown"
else:
- self.knownNamespaces = knownNamespaces
+ self.xmlSource = xmlSource
+ self.createGenerics = createGenerics
self.skipper = False
self.elementstack = []
self.nsstack = []
self.collectContent = None
+ if (knownNamespaces == None):
+ self.knownNamespaces = {}
+ else:
+ self.knownNamespaces = knownNamespaces
+ self.reversedNamespaces = {}
+ for longns, shortns in self.knownNamespaces.iteritems():
+ self.reversedNamespaces[shortns] = longns
+ self.knownTypes = {}
+ if (knownTypes != None):
+ for tag, cls in knownTypes.iteritems():
+ i = tag.rfind(':')
+ if i >= 0:
+ shortns = tag[:i]
+ tag = tag[i+1:]
+ if not self.reversedNamespaces.has_key(shortns):
+ errorString = 'Error unmarshalling XML document from source "%s": knownTypes specifies an unmapped short namespace "%s" for element "%s"' % (self.xmlSource, shortns, tag)
+ raise UnmarshallerException(errorString)
+ longns = self.reversedNamespaces[shortns]
+ tag = '%s:%s' % (longns, tag)
+ self.knownTypes[tag] = cls
+ #printKnownTypes(self.knownTypes, 'Unmarshaller.XMLObjectFactory.__init__')
xml.sax.handler.ContentHandler.__init__(self)
def appendElementStack(self, newElement, newNS):
self.elementstack.append(newElement)
- if (newNS.isEmpty()):
- if (len(self.nsstack) > 0):
- newNS = self.nsstack[-1]
- else:
- newNS.knownTypes = self.knownTypes.copy()
- else:
- if (len(self.nsstack) > 0):
- newNS.setKnownTypes(self.knownTypes, self.knownNamespaces, self.nsstack[-1])
- else:
- newNS.setKnownTypes(self.knownTypes, self.knownNamespaces, None)
+ if (len(self.nsstack) > 0):
+ oldNS = self.nsstack[-1]
+ if newNS.defaultNS == None:
+ newNS.defaultNS = oldNS.defaultNS
+ if newNS.targetNS == None:
+ newNS.targetNS = oldNS.targetNS
+ if len(newNS.nsMap) == 0:
+ newNS.nsMap = oldNS.nsMap
+ elif len(oldNS.nsMap) > 0:
+ map = oldNS.nsMap.copy()
+ map.update(newNS.nsMap)
+ newNS.nsMap = map
self.nsstack.append(newNS)
return newNS
strVal += '>'
self.collectContent.content += strVal
xsname = name
- if name.find(':') > -1: # Strip namespace prefixes for now until actually looking them up in xsd
- name = name[name.rfind(":") + 1:]
+ i = name.rfind(':')
+ if i >= 0:
+ nsname = name[:i]
+ name = name[i+1:]
+ else:
+ nsname = None
element = Element(name, attrs.copy(), xsname=xsname)
# if the element has namespace attributes, process them and add them to our stack
nse = NsElement()
+ objtype = None
for k in attrs.getNames():
if k.startswith('xmlns'):
longNs = attrs[k]
nse.nsMap[shortNs] = longNs
elif k == 'targetNamespace':
nse.targetNS = attrs.getValue(k)
+ elif k == 'objtype':
+ objtype = attrs.getValue(k)
nse = self.appendElementStack(element, nse)
- element.objclass = nse.knownTypes.get(xsname)
+ if nsname != None:
+ if nse.nsMap.has_key(nsname):
+ longname = '%s:%s' % (nse.nsMap[nsname], name)
+## elif objtype == None:
+## errorString = 'Error unmarshalling XML document from source "%s": tag "%s" at line "%d", column "%d" has an undefined namespace' % (self.xmlSource, xsname, self._locator.getLineNumber(), self._locator.getColumnNumber())
+## raise UnmarshallerException(errorString)
+ elif self.reversedNamespaces.has_key(nsname):
+ longname = '%s:%s' % (self.reversedNamespaces[nsname], name)
+ else:
+ longname = xsname
+ elif nse.defaultNS != None:
+ longname = '%s:%s' % (nse.defaultNS, name)
+ else:
+ longname = name
+ element.objtype = objtype
+ element.objclass = self.knownTypes.get(longname)
+ if element.objclass == None and len(self.knownNamespaces) == 0:
+ # handles common case where tags are unqualified and knownTypes are too, but there's a defaultNS
+ element.objclass = self.knownTypes.get(name)
if (hasattr(element.objclass, "__xmlcontent__")):
self.collectContent = element
def endElement(self, name):
## print "[endElement] </%s>" % name
xsname = name
- if name.find(":") > -1: # Strip namespace prefixes for now until actually looking them up in xsd
- name = name[name.find(":") + 1:]
+ i = name.rfind(':')
+ if i >= 0: # Strip namespace prefixes for now until actually looking them up in xsd
+ name = name[i+1:]
if self.skipper:
if xsname == "xs:annotation" or xsname == "xsd:annotation": # here too
self.skipper = False
element, nse = self.popElementStack()
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 (len(element.content) > 0):
strippedElementContent = element.content.strip()
if (len(strippedElementContent) > 0):
constructorarglist.append(element.content)
+ # If the element requires an object, but none is known, use the GenericXMLObject class
+ if ((element.objclass == None) and (element.attrs.get("objtype") == None) and ((len(element.attrs) > 0) or (len(element.children) > 0))):
+ if self.createGenerics:
+ element.objclass = GenericXMLObject
obj = _objectfactory(objtype, constructorarglist, element.objclass)
+ if element.objclass == GenericXMLObject:
+ obj.setXMLAttributes(str(xsname), element.attrs, element.children, nse.nsMap, nse.defaultNS)
complexType = getComplexType(obj)
if (obj != None):
if (hasattr(obj, "__xmlname__") and getattr(obj, "__xmlname__") == "sequence"):
self.elementstack[-1].children = oldChildren
return
if (len(element.attrs) > 0) 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):
ns = attrname[XMLNS_PREFIX_LENGTH:]
else:
ns = ""
- if complexType != None:
+ if complexType != None or element.objclass == GenericXMLObject:
if not hasattr(obj, "__xmlnamespaces__"):
obj.__xmlnamespaces__ = {ns:attr}
elif ns not in obj.__xmlnamespaces__:
xsdElement = complexType.findElement(attrname)
if (xsdElement != None):
type = xsdElement.type
-## print 'Unmarshalling element "%s", attribute "%s" with type "%s"' % (name, xsdElement.name, type)
if (type != None):
if (type == TYPE_QNAME):
attr = nse.expandQName(name, attrname, attr)
### ToDO remove maxOccurs hack after bug 177 is fixed
if attrname == "maxOccurs" and attr == "unbounded":
attr = "-1"
- attr = _objectfactory(type, attr)
+ try:
+ attr = _objectfactory(type, attr)
+ except Exception, exceptData:
+ errorString = 'Error unmarshalling attribute "%s" at line %d, column %d in XML document from source "%s": %s' % (attrname, self._locator.getLineNumber(), self._locator.getColumnNumber(), self.xmlSource, str(exceptData))
+ raise UnmarshallerException(errorString)
try:
setattrignorecase(obj, _toAttrName(obj, attrname), attr)
except AttributeError:
- errorString = 'Error unmarshalling XML document at line %i, column %i: The object type of attribute "%s" of XML element "%s": not specified or known' % (self._locator.getLineNumber(), self._locator.getColumnNumber(), attrname, name)
+ errorString = 'Error setting value of attribute "%s" at line %d, column %d in XML document from source "%s": object type of XML element "%s" is not specified or known' % (attrname, self._locator.getLineNumber(), self._locator.getColumnNumber(), self.xmlSource, name)
raise UnmarshallerException(errorString)
## obj.__dict__[_toAttrName(obj, attrname)] = attr
# stuff any child attributes meant to be in a sequence via the __xmlflattensequence__
flattenDict[str(xmlnametuple)] = sequencename
else:
for xmlname in xmlnametuple:
-## print "[endElement]: adding flattenDict[%s] = %s" % (xmlname, sequencename)
flattenDict[xmlname] = sequencename
else:
raise Exception("Invalid type for __xmlflattensequence___ : it must be a dict")
# reattach an object"s attributes to it
for childname, child in element.children:
-## print "[endElement] childname is: ", childname, "; child is: ", child
if (childname in flattenDict):
sequencename = _toAttrName(obj, flattenDict[childname])
if (not hasattr(obj, sequencename)):
else:
obj[childname] = child
else:
-## print "childname = %s, obj = %s, child = %s" % (childname, repr(obj), repr(child))
- try:
- setattrignorecase(obj, _toAttrName(obj, childname), child)
- except AttributeError:
- raise MarshallerException("Error unmarshalling child element \"%s\" of XML element \"%s\": object type not specified or known" % (childname, name))
-## obj.__dict__[_toAttrName(obj, childname)] = child
+ # don't replace a good attribute value with a bad one
+ childAttrName = _toAttrName(obj, childname)
+ if (not hasattr(obj, childAttrName)) or (getattr(obj, childAttrName) == None) or (getattr(obj, childAttrName) == []) or (not isinstance(child, GenericXMLObject)):
+ try:
+ setattrignorecase(obj, childAttrName, child)
+ except AttributeError:
+ raise MarshallerException("Error unmarshalling child element \"%s\" of XML element \"%s\": object type not specified or known" % (childname, name))
if (complexType != None):
for element in complexType.elements:
if (len(self.elementstack) > 0):
## 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
break
## if (name.startswith("__") and not name.endswith("__")):
## name = "_%s%s" % (obj.__class__.__name__, name)
- return name
+ return str(name)
+
+def printKnownTypes(kt, where):
+ print 'KnownTypes from %s' % (where)
+ for tag, cls in kt.iteritems():
+ print '%s => %s' % (tag, str(cls))
__typeMappingXsdToLang = {
"string": "str",
if xsdType.startswith(XMLSCHEMA_XSD_URL):
xsdType = xsdType[len(XMLSCHEMA_XSD_URL)+1:]
elif xsdType.startswith(AG_URL):
- xsdType = xsdType[len(AG_URL)+1:]
+ xsdType = xsdType[len(AG_URL)+1:]
langType = __typeMappingXsdToLang.get(xsdType)
if (langType == None):
raise Exception("Unknown xsd type %s" % xsdType)
else:
return str(langValue)
-def unmarshal(xmlstr, knownTypes=None, knownNamespaces=None, xmlSource=None):
- objectfactory = XMLObjectFactory(knownTypes, knownNamespaces)
+def unmarshal(xmlstr, knownTypes=None, knownNamespaces=None, xmlSource=None, createGenerics=False):
+ objectfactory = XMLObjectFactory(knownTypes, knownNamespaces, xmlSource, createGenerics)
+ # on Linux, pyXML's sax.parseString fails when passed unicode
+ if (not sysutils.isWindows()):
+ xmlstr = str(xmlstr)
try:
xml.sax.parseString(xmlstr, objectfactory)
except xml.sax.SAXParseException, errorData:
return objectfactory.getRootObject()
def marshal(obj, elementName=None, prettyPrint=False, marshalType=True, indent=0, knownTypes=None, knownNamespaces=None, encoding=-1):
-## print '[marshal] entered with elementName = "%s"' % (elementName)
worker = XMLMarshalWorker(prettyPrint=prettyPrint, marshalType=marshalType, knownTypes=knownTypes, knownNamespaces=knownNamespaces)
if obj != None and hasattr(obj, '__xmldeepexclude__'):
worker.xmldeepexclude = obj.__xmldeepexclude__
xmlstr = "".join(worker._marshal(obj, elementName, indent=indent))
- if (isinstance(encoding, basestring)):
- return '<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, xmlstr.encode(encoding))
- elif (encoding == None):
+ aglogging.info(xmlMarshallerLogger, "marshal produced string of type %s", type(xmlstr))
+ if (encoding == None):
return xmlstr
- else:
- return '<?xml version="1.0" encoding="%s"?>\n%s' % (sys.getdefaultencoding(), xmlstr)
+ if (not isinstance(encoding, basestring)):
+ encoding = sys.getdefaultencoding()
+ if (not isinstance(xmlstr, unicode)):
+ xmlstr = xmlstr.decode()
+ xmlstr = u'<?xml version="1.0" encoding="%s"?>\n%s' % (encoding, xmlstr)
+ return xmlstr.encode(encoding)
class XMLMarshalWorker(object):
def __init__(self, marshalType=True, prettyPrint=False, knownTypes=None, knownNamespaces=None):
newNS.prefix = self.nsstack[-1].prefix
else:
newNS.prefix = ''
- if hasattr(obj, "__xmldefaultnamespace__"):
+ if obj != None and hasattr(obj, "__xmldefaultnamespace__"):
longPrefixNS = getattr(obj, "__xmldefaultnamespace__")
if longPrefixNS == defaultLongNS:
newNS.prefix = ''
if v == longPrefixNS:
newNS.prefix = k + ':'
break;
-## print '[appendNSStack] found longPrefixNS in nameSpaces = "%s"' % (newNS.prefix)
except:
if (longPrefixNS in asDict(self.knownNamespaces)):
newNS.prefix = self.knownNamespaces[longPrefixNS] + ':'
else:
raise MarshallerException('Error marshalling __xmldefaultnamespace__ ("%s") not defined in namespace stack' % (longPrefixNS))
- if hasattr(obj, "targetNamespace"):
+ if obj != None and hasattr(obj, "targetNamespace"):
newNS.targetNS = obj.targetNamespace
elif len(self.nsstack) > 0:
newNS.targetNS = self.nsstack[-1].targetNS
def _marshal(self, obj, elementName=None, nameSpacePrefix="", indent=0):
if (obj != None):
- xmlMarshallerLogger.debug("--> _marshal: elementName=%s%s, type=%s, obj=%s, indent=%d" % (nameSpacePrefix, elementName, type(obj), str(obj), indent))
+ aglogging.debug(xmlMarshallerLogger, "--> _marshal: elementName=%s%s, type=%s, obj=%s, indent=%d", nameSpacePrefix, elementName, type(obj), str(obj), indent)
else:
- xmlMarshallerLogger.debug("--> _marshal: elementName=%s%s, obj is None, indent=%d" % (nameSpacePrefix, elementName, indent))
+ aglogging.debug(xmlMarshallerLogger, "--> _marshal: elementName=%s%s, obj is None, indent=%d", nameSpacePrefix, elementName, indent)
+ if ((obj != None) and (hasattr(obj, 'preMarshal'))):
+ obj.preMarshal()
excludeAttrs = []
excludeAttrs.extend(self.xmldeepexclude)
if hasattr(obj, "__xmlexclude__"):
newline = ""
increment = 0
## Determine the XML element name. If it isn"t specified in the
- ## parameter list, look for it in the __xmlname__ Lang
- ## attribute, else use the default generic BASETYPE_ELEMENT_NAME.
+ ## 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:
elementName = nameSpacePrefix + BASETYPE_ELEMENT_NAME
else:
elementName = nameSpacePrefix + elementName
-## print '[XMLMarshalWorker._marshal] elementName "%s"; nameSpaceAttrs is "%s"' % (elementName, nameSpaceAttrs)
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:
- xsdPrefix = kShort + ':'
+ if kShort != DEFAULT_NAMESPACE_KEY:
+ xsdPrefix = kShort + ':'
+ else:
+ xsdPrefix = ''
break
else:
xsdPrefix = 'xs:'
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__ and __xmldeepexclude__ attributes.
xmlattributes = obj.__xmlattributes__
members_to_skip.extend(xmlattributes)
for attr in xmlattributes:
-## print 'Processing element "%s"; attribute "%s"' % (elementName, attr)
internalAttrName = attr
ifDefPy()
if (attr.startswith("__") and not attr.endswith("__")):
endIfDef()
# Fail silently if a python attribute is specified to be
# an XML attribute but is missing.
-## print "marshal: processing attribute ", internalAttrName
attrNameSpacePrefix = ""
if hasattr(obj, "__xmlattrnamespaces__"):
for nameSpaceKey, nameSpaceAttributes in getattr(obj, "__xmlattrnamespaces__").iteritems():
else:
value = objutils.toDiffableRepr(value)
- objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, saxutils.escape(value))
- ## print "marshal: new objattrs is: ", objattrs
+ objattrs += ' %s%s="%s"' % (attrNameSpacePrefix, attr, utillang.escape(value))
if (obj == None):
xmlString = [""]
elif isinstance(obj, bool):
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, saxutils.escape(obj.encode()), elementName, newline)]
+ 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, saxutils.escape(obj), elementName, newline)]
+ 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 = ""
elif hasattr(obj, "__xmlcontent__"):
contentValue = getattr(obj, obj.__xmlcontent__)
if contentValue == None:
- contentValue = ''
+ xmlString = ["%s<%s%s%s/>%s" % (prefix, elementName, nameSpaceAttrs, objattrs, newline)]
else:
- contentValue = saxutils.escape(contentValue)
- xmlString = ["%s<%s%s%s>%s</%s>%s" % (prefix, elementName, nameSpaceAttrs, objattrs, contentValue, elementName, newline)]
+ 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 (self.isKnownType(elementName) == True):
+ if (isinstance(obj, GenericXMLObject)):
+ objTypeStr = ""
+ elif (self.isKnownType(elementName) == True):
objTypeStr = ""
else:
objTypeStr = self._genObjTypeStr("%s.%s" % (obj.__class__.__module__, className))
if hasattr(obj, "__xmlbody__"):
xmlbody = getattr(obj, obj.__xmlbody__)
if xmlbody != None:
- xmlMemberString.append(xmlbody)
+ xmlMemberString.append(utillang.escape(xmlbody))
else:
if hasattr(obj, "__xmlattrgroups__"):
attrGroups = obj.__xmlattrgroups__.copy()
xmlname = None
if (len(xmlnametuple) == 1):
xmlname = xmlnametuple[0]
- ## ix = 0
if not isinstance(value, (list, tuple)):
value = [value]
for seqitem in value:
- ## xmlname = xmlnametuple[ix]
- ## ix += 1
- ## if (ix >= len(xmlnametuple)):
- ## ix = 0
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
- xmlMemberString.extend(self._marshal(value, xmlname, subElementNameSpacePrefix, indent=indent+increment))
+ 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]
xmlString.append("><![CDATA[%s]]></%s>%s" % (cdataContent, elementName, newline))
else:
xmlString.append("/>%s" % newline)
- ## return xmlString
- xmlMarshallerLogger.debug("<-- _marshal: %s" % str(xmlString))
+ if aglogging.isEnabledForDebug(xmlMarshallerLogger):
+ aglogging.debug(xmlMarshallerLogger, "<-- _marshal: %s", objutils.toDiffableString(xmlString))
#print "<-- _marshal: %s" % str(xmlString)
self.popNSStack()
return xmlString