+            # the value doesn't have a namespace and we couldn't map it to an XSD type...what to do?
+            # (a) just write it, as is, and hope it's in the default namespace (for now)
+            # (b) throw an exception so we can track down the bad code (later)
+            return value
+        if (longNS in self.nsstack[-1].nameSpaces.values()):
+            for kShort, vLong in self.nsstack[-1].nameSpaces.iteritems():
+                if vLong == longNS:
+                    shortNS = kShort
+                    break
+        else:
+            shortNS = longNS    # if we can't find the long->short mappping, just use longNS
+        if shortNS == DEFAULT_NAMESPACE_KEY:
+            value = value[i+1:]
+        else:
+            value = shortNS + ':' + value[i+1:]
+        return value
+
+    def _genObjTypeStr(self, typeString):
+        if self.marshalType:
+            return ' objtype="%s"' % typeString
+        return ""
+            
+    def _marshal(self, obj, elementName=None, nameSpacePrefix="", indent=0):
+        if (obj != None):
+            aglogging.debug(xmlMarshallerLogger, "--> _marshal: elementName=%s%s, type=%s, obj=%s, indent=%d", nameSpacePrefix, elementName, type(obj), str(obj), indent)
+        else:
+            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__"):
+            excludeAttrs.extend(obj.__xmlexclude__)
+        prettyPrint = self.prettyPrint
+        knownTypes = self.knownTypes
+        xmlString = None
+        if self.prettyPrint or indent:
+            prefix = " "*indent
+            newline = "\n"
+            increment = 2
+        else:
+            prefix = ""
+            newline = ""
+            increment = 0
+        ## Determine the XML element name. If it isn"t specified in the
+        ## 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()