Improvements in XmlMarshaller: any Python variable may be the root of a structure to marshall.
This commit is contained in:
parent
37c252c3fd
commit
15ef6f334d
|
@ -17,7 +17,7 @@
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA.
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
import xml.sax, difflib
|
import xml.sax, difflib, types
|
||||||
from xml.sax.handler import ContentHandler, ErrorHandler
|
from xml.sax.handler import ContentHandler, ErrorHandler
|
||||||
from xml.sax.xmlreader import InputSource
|
from xml.sax.xmlreader import InputSource
|
||||||
from appy.shared import UnicodeBuffer
|
from appy.shared import UnicodeBuffer
|
||||||
|
@ -401,6 +401,15 @@ class XmlMarshaller:
|
||||||
self.dumpString(res, value)
|
self.dumpString(res, value)
|
||||||
elif isinstance(value, bool):
|
elif isinstance(value, bool):
|
||||||
res.write(self.trueFalse[value])
|
res.write(self.trueFalse[value])
|
||||||
|
elif self.isAnObject(value):
|
||||||
|
if hasattr(value, 'absolute_url'):
|
||||||
|
res.write(value.absolute_url())
|
||||||
|
else:
|
||||||
|
res.write(value)
|
||||||
|
# We could dump the entire object content, too. Maybe we could add a
|
||||||
|
# parameter to the marshaller to know how to marshall objects
|
||||||
|
# (produce an ID, an URL, include the entire tag but we need to take
|
||||||
|
# care of circular references,...)
|
||||||
else:
|
else:
|
||||||
res.write(value)
|
res.write(value)
|
||||||
|
|
||||||
|
@ -434,23 +443,40 @@ class XmlMarshaller:
|
||||||
self.dumpValue(res, fieldValue, fieldType)
|
self.dumpValue(res, fieldValue, fieldType)
|
||||||
res.write('</'); res.write(fieldName); res.write('>')
|
res.write('</'); res.write(fieldName); res.write('>')
|
||||||
|
|
||||||
|
def isAnObject(self, instance):
|
||||||
|
'''Returns True if p_instance is a class instance, False if it is a
|
||||||
|
basic type, or tuple, sequence, etc.'''
|
||||||
|
iType = type(instance)
|
||||||
|
if iType == types.InstanceType:
|
||||||
|
return True
|
||||||
|
elif iType.__name__ == 'ImplicitAcquirerWrapper':
|
||||||
|
# This is the case with Archetype instances
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def marshall(self, instance, objectType='popo'):
|
def marshall(self, instance, objectType='popo'):
|
||||||
'''Returns in a UnicodeBuffer the XML version of p_instance. If
|
'''Returns in a UnicodeBuffer the XML version of p_instance. If
|
||||||
p_instance corresponds to a Plain Old Python Object, specify 'popo'
|
p_instance corresponds to a Plain Old Python Object, specify 'popo'
|
||||||
for p_objectType. If p_instance corresponds to an Archetypes object
|
for p_objectType. If p_instance corresponds to an Archetypes object
|
||||||
(Zope/Plone), specify 'archetype' for p_objectType. if p_instance is
|
(Zope/Plone), specify 'archetype' for p_objectType. if p_instance is
|
||||||
a Appy object, specify "appy" as p_objectType.'''
|
a Appy object, specify "appy" as p_objectType. If p_instance is not
|
||||||
|
an instance at all, but another Python data structure or basic type,
|
||||||
|
p_objectType is ignored.'''
|
||||||
|
# Call the XmlMarshaller constructor if it hasn't been called yet.
|
||||||
if not hasattr(self, 'cdata'):
|
if not hasattr(self, 'cdata'):
|
||||||
# The constructor has not been called. Do it now.
|
|
||||||
XmlMarshaller.__init__(self)
|
XmlMarshaller.__init__(self)
|
||||||
|
# Create the buffer where the XML result will be dumped.
|
||||||
res = UnicodeBuffer()
|
res = UnicodeBuffer()
|
||||||
# Dump the XML prologue and root element
|
# Dump the XML prologue
|
||||||
|
res.write(self.xmlPrologue)
|
||||||
|
if self.isAnObject(instance):
|
||||||
|
# Determine object ID
|
||||||
if objectType in ('archetype', 'appy'):
|
if objectType in ('archetype', 'appy'):
|
||||||
objectId = instance.UID() # ID in DB
|
objectId = instance.UID() # ID in DB
|
||||||
else: objectId = str(id(instance)) # ID in RAM
|
else:
|
||||||
res.write(self.xmlPrologue)
|
objectId = str(id(instance)) # ID in RAM
|
||||||
res.write('<'); res.write(self.rootElementName)
|
res.write('<'); res.write(self.rootElementName)
|
||||||
res.write(' type="object" id="'); res.write(objectId); res.write('">')
|
res.write(' type="object" id="');res.write(objectId);res.write('">')
|
||||||
# Dump the object ID and the value of the fields that must be dumped
|
# Dump the object ID and the value of the fields that must be dumped
|
||||||
if objectType == 'popo':
|
if objectType == 'popo':
|
||||||
for fieldName, fieldValue in instance.__dict__.iteritems():
|
for fieldName, fieldValue in instance.__dict__.iteritems():
|
||||||
|
@ -460,8 +486,8 @@ class XmlMarshaller:
|
||||||
elif self.fieldsToMarshall == 'all':
|
elif self.fieldsToMarshall == 'all':
|
||||||
mustDump = True
|
mustDump = True
|
||||||
else:
|
else:
|
||||||
if (type(self.fieldsToMarshall) in self.sequenceTypes) and \
|
if (type(self.fieldsToMarshall) in self.sequenceTypes) \
|
||||||
(fieldName in self.fieldsToMarshall):
|
and (fieldName in self.fieldsToMarshall):
|
||||||
mustDump = True
|
mustDump = True
|
||||||
if mustDump:
|
if mustDump:
|
||||||
self.dumpField(res, fieldName, fieldValue)
|
self.dumpField(res, fieldName, fieldValue)
|
||||||
|
@ -478,8 +504,8 @@ class XmlMarshaller:
|
||||||
elif self.fieldsToMarshall == 'all_with_metadata':
|
elif self.fieldsToMarshall == 'all_with_metadata':
|
||||||
mustDump = True
|
mustDump = True
|
||||||
else:
|
else:
|
||||||
if (type(self.fieldsToMarshall) in self.sequenceTypes) and \
|
if (type(self.fieldsToMarshall) in self.sequenceTypes) \
|
||||||
(field.getName() in self.fieldsToMarshall):
|
and (field.getName() in self.fieldsToMarshall):
|
||||||
mustDump = True
|
mustDump = True
|
||||||
if mustDump:
|
if mustDump:
|
||||||
fieldType = 'basic'
|
fieldType = 'basic'
|
||||||
|
@ -487,7 +513,7 @@ class XmlMarshaller:
|
||||||
fieldType = 'file'
|
fieldType = 'file'
|
||||||
elif field.type == 'reference':
|
elif field.type == 'reference':
|
||||||
fieldType = 'ref'
|
fieldType = 'ref'
|
||||||
self.dumpField(res, field.getName(), field.get(instance),
|
self.dumpField(res, field.getName(),field.get(instance),
|
||||||
fieldType=fieldType)
|
fieldType=fieldType)
|
||||||
if objectType == 'appy':
|
if objectType == 'appy':
|
||||||
# Dump the object history.
|
# Dump the object history.
|
||||||
|
@ -497,12 +523,15 @@ class XmlMarshaller:
|
||||||
history = instance.workflow_history[wfInfo[0].id]
|
history = instance.workflow_history[wfInfo[0].id]
|
||||||
for event in history:
|
for event in history:
|
||||||
res.write('<event type="object">')
|
res.write('<event type="object">')
|
||||||
for k, v in event.iteritems(): self.dumpField(res, k, v)
|
for k, v in event.iteritems():
|
||||||
|
self.dumpField(res, k, v)
|
||||||
res.write('</event>')
|
res.write('</event>')
|
||||||
res.write('</history>')
|
res.write('</history>')
|
||||||
self.marshallSpecificElements(instance, res)
|
self.marshallSpecificElements(instance, res)
|
||||||
# Return the result
|
|
||||||
res.write('</'); res.write(self.rootElementName); res.write('>')
|
res.write('</'); res.write(self.rootElementName); res.write('>')
|
||||||
|
else:
|
||||||
|
self.dumpField(res, self.rootElementName, instance)
|
||||||
|
# Return the result
|
||||||
res = res.getValue()
|
res = res.getValue()
|
||||||
if not self.dumpUnicode:
|
if not self.dumpUnicode:
|
||||||
res = res.encode('utf-8')
|
res = res.encode('utf-8')
|
||||||
|
|
Loading…
Reference in a new issue