📄 xmlmarshaller.py
字号:
#----------------------------------------------------------------------------# Name: xmlmarshaller.py# Purpose:## Authors: John Spurling, Joel Hare, Jeff Norton, Alan Mullendore## Created: 7/28/04# CVS-ID: $Id: xmlmarshaller.py,v 1.7 2006/04/20 06:25:50 RD Exp $# Copyright: (c) 2004-2005 ActiveGrid, Inc.# License: wxWindows License#----------------------------------------------------------------------------import sysfrom types import *from activegrid.util.lang import *import loggingifDefPy()import xml.saximport xml.sax.handlerimport xml.sax.saxutilsimport datetimeendIfDef()import activegrid.util.utillang as utillangimport activegrid.util.objutils as objutilsimport activegrid.util.sysutils as sysutilsimport activegrid.util.aglogging as agloggingMODULE_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:name: __xmlname__type: stringdescription: the name of the xml element for the marshalled objectname: __xmlattributes__type: tuple or listdescription: the name(s) of the Lang string attribute(s) to bemarshalled as xml attributes instead of nested xml elements. currentlythese can only be strings since there"s not a way to get the typeinformation back when unmarshalling.name: __xmlexclude__type: tuple or listdescription: the name(s) of the lang attribute(s) to skip whenmarshalling.name: __xmlrename__type: dictdescription: describes an alternate Lang <-> XML name mapping. Normally the name mapping is the identity function. __xmlrename__overrides that. The keys are the Lang names, the values are theirassociated XML names.name: __xmlflattensequence__type: dict, tuple, or listdescription: the name(s) of the Lang sequence attribute(s) whoseitems are to be marshalled as a series of xml elements (with anoptional keyword argument that specifies the element name to use) asopposed to containing them in a separate sequence element, e.g.:myseq = (1, 2)<!-- normal way of marshalling --><myseq> <item objtype="int">1</item> <item objtype="int">2</item></myseq><!-- with __xmlflattensequence__ set to {"myseq": "squish"} --><squish objtype="int">1</squish><squish objtype="int">2</squish>name: __xmlnamespaces__type: dictdescription: a dict of the namespaces that the object uses. Each itemin the dict should consist of a prefix,url combination where the key isthe prefix and url is the value, e.g.:__xmlnamespaces__ = { "xsd":"http://www.w3c.org/foo.xsd" }name: __xmldefaultnamespace__type: Stringdescription: the prefix of a namespace defined in __xmlnamespaces__ thatshould be used as the default namespace for the object.name: __xmlattrnamespaces__type: dictdescription: a dict assigning the Lang object"s attributes to the namespacesdefined in __xmlnamespaces__. Each item in the dict should consist of aprefix,attributeList combination where the key is the prefix and the value isa list of the Lang attribute names. e.g.:__xmlattrnamespaces__ = { "ag":["firstName", "lastName", "addressLine1", "city"] }name: __xmlattrgroups__type: dictdescription: 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 includewithin it. e.g.__xmlattrgroups__ = {"name": ["firstName", "lastName"], "address": ["addressLine1", "city", "state", "zip"]}name: __xmlcdatacontent__type: stringdescription: value is the name of a string attribute that should be assigned CDATA content from thesource document and that should be marshalled as CDATA.__xmlcdatacontent__ = "messyContent""""global xmlMarshallerLoggerxmlMarshallerLogger = logging.getLogger("activegrid.util.xmlmarshaller.marshal")# INFO : low-level info# DEBUG : debugging info################################################################################## module exceptions#################################################################################class Error(Exception): """Base class for errors in this module.""" passclass UnhandledTypeException(Error): """Exception raised when attempting to marshal an unsupported type. """ def __init__(self, typename): self.typename = typename def __str__(self): return "%s is not supported for marshalling." % str(self.typename)class XMLAttributeIsNotStringType(Error): """Exception raised when an object"s attribute is specified to be marshalled as an XML attribute of the enclosing object instead of a nested element. """ def __init__(self, attrname, typename): self.attrname = attrname self.typename = typename def __str__(self): return """%s was set to be marshalled as an XML attribute instead of a nested element, but the object"s type is %s, not string.""" % (self.attrname, self.typename)class MarshallerException(Exception): passclass UnmarshallerException(Exception): pass ################################################################################## constants and such#################################################################################XMLNS = "xmlns"XMLNS_PREFIX = XMLNS + ":"XMLNS_PREFIX_LENGTH = len(XMLNS_PREFIX)DEFAULT_NAMESPACE_KEY = "__DEFAULTNS__"TYPE_QNAME = "QName"XMLSCHEMA_XSD_URL = "http://www.w3.org/2001/XMLSchema"AG_URL = "http://www.activegrid.com/ag.xsd"BASETYPE_ELEMENT_NAME = "item"DICT_ITEM_NAME = "qqDictItem"DICT_ITEM_KEY_NAME = "key"DICT_ITEM_VALUE_NAME = "value"# 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__",## "__xmlattrgroups__")################################################################################## classes and functions#################################################################################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__: if attr.lower() == namelow: object.__dict__[attr] = value return object.__dict__[name] = valuedef getComplexType(obj): if (hasattr(obj, "_instancexsdcomplextype")): return obj._instancexsdcomplextype if (hasattr(obj, "__xsdcomplextype__")): return obj.__xsdcomplextype__ return Nonedef _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]) else: obj = objclass(*objargs) else: 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.attrs = attrs self.content = "" self.children = [] self.objclass = None self.xsname = xsname self.objtype = None def getobjtype(self):# objtype = self.attrs.get("objtype") objtype = self.objtype if (objtype == None): if (len(self.children) > 0): objtype = "dict" else: objtype = "str" return objtype
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -