simple xml pickle

Michael Stenner mstenner at phy.duke.edu
Thu Sep 5 02:31:47 CEST 2002


On Wed, Sep 04, 2002 at 01:29:51PM -0400, Michael Stenner wrote:
> The xml marshalling does almost exactly what I want, and the
> modifications to make it "standalone" for Python 2.2 were very easy
> (patch forthcoming) so I may just stick with that.  Nonetheless, I'll
> look at xml_pickle again and see what I can see.

Results:

  With David's hint, xml_pickle.py was also fairly easy to make work
  with python 2.2 in a standalone fashion.  Here are the patches to
  make both the PyXML marshaller and xml_pickle.py work as standalone
  files with python 2.2 (probably 2.x, but I haven't tested it).

  I haven't really tested either of these.  I just tweeked them so
  that they passed their own built-in tests.

  generic.py.diff should be applied to xml.marshal.generic.py from
  PyXML 0.8.

  xml_pickle.py.diff should be applied to xml_pickle.py 0.51.

Now I just need to decide which I want to use :)

					-Michael
-- 
  Michael Stenner                       Office Phone: 919-660-2513
  Duke University, Dept. of Physics       mstenner at phy.duke.edu
  Box 90305, Durham N.C. 27708-0305
-------------- next part --------------
--- generic.py.orig	Wed Sep  4 20:19:58 2002
+++ generic.py	Wed Sep  4 10:34:45 2002
@@ -6,7 +6,12 @@
 
 from types import *
 import string
-from xml.sax import saxlib, saxexts
+import xml.sax
+from xml.sax.handler import EntityResolver, DTDHandler, ContentHandler,\
+     ErrorHandler
+
+class HandlerBase(EntityResolver, DTDHandler, ContentHandler,\
+                  ErrorHandler): pass
 
 # Basic marshaller class, customizable by overriding it and
 # changing various attributes and methods.
@@ -20,7 +25,7 @@
         return cmp(ta.__name__, tb.__name__)
     return cmp(a,b)
 
-class Marshaller(saxlib.HandlerBase):
+class Marshaller(HandlerBase):
     # XML version and DOCTYPE declaration
     PROLOGUE = '<?xml version="1.0"?>'
     DTD = ""
@@ -251,7 +256,7 @@
 
 TUPLE = {} ; LIST = {} ; DICT = {}
 
-class Unmarshaller(saxlib.HandlerBase):
+class Unmarshaller(HandlerBase):
     # This dictionary maps element names to the names of starting and ending
     # functions to call when unmarshalling them.  My convention is to
     # name them um_start_foo and um_end_foo, but do whatever you like.
@@ -314,9 +319,9 @@
 
     def _load(self, file):
         "Read one value from the open file"
-        p=saxexts.make_parser()
-        p.setDocumentHandler(self)
-        p.parseFile(file)
+        p=xml.sax.make_parser()
+        p.setContentHandler(self)
+        p.parse(file)
         assert len(self.data_stack) == 1
         # leave the instance in a steady state
         result = self.data_stack[0]
@@ -358,9 +363,9 @@
         sm, em = self.unmarshal_meth[ name ]
         if sm is not None: return sm(name,attrs)
 
-    def characters(self, ch, start, length):
+    def characters(self, ch):
         if self.accumulating_chars:
-            self.data_stack[-1].append(ch[start:start+length])
+            self.data_stack[-1].append(ch)
 
     def endElement(self, name):
         # Call the ending method
-------------- next part --------------
--- xml_pickle.py.orig	Tue Sep  3 18:38:48 2002
+++ xml_pickle.py	Wed Sep  4 20:18:34 2002
@@ -206,7 +206,7 @@
                      '<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">\n',
                      '<PyObject class="%s" id="%s">\n'
                          % (_klass(self.py_obj),id_)]
-        for name in dir(self.py_obj):
+        for name in self.py_obj.__dict__.keys():
             xml_lines.append(_attr_tag(name, getattr(self, name)))
         xml_lines.append('</PyObject>\n')
         return string.join(xml_lines,'')
@@ -226,36 +226,36 @@
             # Add all the subnodes to PyObject container
             container = thing_from_dom(node, obj_from_node(node))
             try:
-                id = node.attributes[('', 'id')].value
+                id = node.attributes['id'].value
                 visited[id] = container
             except KeyError:
                 pass
 
         elif node.nodeName == 'attr':
             try:
-                node_type = node.attributes[('','type')].value
+                node_type = node.attributes['type'].value
             except:
                 print "node", node.attributes, repr(node.attributes)
                 print node.attributes.keys()
                 raise ValueError   # WHAT?!
-            node_name = node.attributes[('', 'name')].value
+            node_name = node.attributes['name'].value
             if node_name == '__parent__' and EXCLUDE_PARENT_ATTR:
                 # Do not pickle [xml_objectify] bookkeeping attribute
                 pass
             elif node_type == 'None':
                 setattr(container, node_name, None)
             elif node_type == 'numeric':
-                node_val = safe_eval(node.attributes[('','value')].value)
+                node_val = safe_eval(node.attributes['value'].value)
                 setattr(container, node_name, node_val)
             elif node_type == 'string':
-                node_val = node.attributes[('','value')].value
+                node_val = node.attributes['value'].value
                 node_val = unsafe_string(node_val)
                 setattr(container, node_name, node_val)
             elif node_type == 'list':
                 subcontainer = thing_from_dom(node, [])
                 setattr(container, node_name, subcontainer)
                 try:
-                    id = node.attributes[('', 'id')].value
+                    id = node.attributes['id'].value
                     visited[id] = subcontainer
                 except KeyError:
                     pass
@@ -263,7 +263,7 @@
                 subcontainer = thing_from_dom(node, []) # use list then convert
                 setattr(container, node_name, tuple(subcontainer))
                 try:
-                    id = node.attributes[('', 'id')].value
+                    id = node.attributes['id'].value
                     visited[id] = subcontainer
                 except KeyError:
                     pass
@@ -284,7 +284,7 @@
                 subcontainer = thing_from_dom(node, {})
                 setattr(container, node_name, subcontainer)
                 try:
-                    id = node.attributes[('', 'id')].value
+                    id = node.attributes['id'].value
                     visited[id] = subcontainer
                 except KeyError:
                     pass
@@ -292,16 +292,16 @@
                 subcontainer = thing_from_dom(node, obj_from_node(node))
                 setattr(container, node_name, subcontainer)
                 try:
-                    id = node.attributes[('', 'id')].value
+                    id = node.attributes['id'].value
                     visited[id] = subcontainer
                 except KeyError:
                     pass
             elif node_type == 'mxDateTime':
-                parts = node.attributes[('','value')].value.split()
+                parts = node.attributes['value'].value.split()
                 node_val = apply(mx.DateTime.DateTime,map(float,parts))
                 setattr(container, node_name, node_val)
             elif node_type == 'ref':
-                ref_id = node.attributes[('', 'refid')].value
+                ref_id = node.attributes['refid'].value
                 setattr(container, node_name, visited[ref_id])
 
         elif node.nodeName in ['item', 'key', 'val']:
@@ -310,12 +310,12 @@
             # all cases, elif's are defined for mutable types. Furthermore,
             # there should only ever be *one* item in any key/val list,
             # but we again rely on other validation of the XML happening.
-            node_type = str(node.attributes[('','type')].value)
+            node_type = str(node.attributes['type'].value)
             if  node_type == 'numeric':
-                node_val = safe_eval(node.attributes[('','value')].value)
+                node_val = safe_eval(node.attributes['value'].value)
                 container.append(node_val)
             elif node_type == 'string':
-                node_val = node.attributes[('','value')].value
+                node_val = node.attributes['value'].value
                 node_val = unsafe_string(node_val)
                 container.append(node_val)
             elif node_type in ('list',array_type):
@@ -331,7 +331,7 @@
                 subcontainer = thing_from_dom(node, obj_from_node(node))
                 container.append(subcontainer)
             elif node_type == 'mxDateTime':
-                parts = node.attributes[('','value')].value.split()
+                parts = node.attributes['value'].value.split()
                 node_val = apply(mx.DateTime.DateTime,map(float,parts))
                 container.append(node_val)
 
@@ -350,7 +350,7 @@
     # Get classname of object (with fallback to 'PyObject')
     try:
         if node.attributes:
-            klass = node.attributes[('','class')].value
+            klass = node.attributes['class'].value
         else:
             klass = 'PyObject'
     except KeyError: klass = 'PyObject'
@@ -452,7 +452,7 @@
             visited[id(thing)] = 1
             start_tag = start_tag + 'type="PyObject" class="%s" id="%s">\n' \
                                               % (_klass(thing), id(thing))
-            for name in dir(thing):
+            for name in thing.__dict__.keys():
                 tag_body.append(_attr_tag(name, getattr(thing, name), level+1))
     elif '%s' % type(thing) == "<type 'SRE_Pattern'>":
         # SRE_Pattern objects are extension objects, so not


More information about the Python-list mailing list