Make deserializer use a temporary tree of xml.etree.ElementTree.Element
authorNick Downing <nick@ndcode.org>
Tue, 29 Jan 2019 00:48:36 +0000 (11:48 +1100)
committerNick Downing <nick@ndcode.org>
Tue, 29 Jan 2019 02:01:57 +0000 (13:01 +1100)
pitree.t
skel/element.py

index 2dd216c..79ee785 100644 (file)
--- a/pitree.t
+++ b/pitree.t
@@ -264,8 +264,8 @@ def generate_class_or_field_def(self, context):
     context.indent = indent_save2
     context.fout.write(
       '''{0:s}  return _element
-{1:s}def deserialize(self, ref_list):
-{2:s}  {3:s}.deserialize(self, ref_list)
+{1:s}def deserialize(self, _element, ref_list):
+{2:s}  {3:s}.deserialize(self, _element, ref_list)
 '''.format(
         context.indent,
         context.indent,
@@ -284,7 +284,7 @@ def generate_class_or_field_def(self, context):
           context.field_name,
           i[0].generate_deserialize(
             context,
-            'json.loads(self.get(\'{0:s}\'{1:s}))'.format(
+            'json.loads(_element.get(\'{0:s}\'{1:s}))'.format(
               context.field_name,
               (
                 ', \'{0:s}\''.format(
index d3b534e..f42caee 100644 (file)
@@ -183,9 +183,8 @@ class Element:
         child_element.tail = tail
       element.append(child_element)
     return element
-  def deserialize(self, ref_list):
-    for i in self:
-      i.deserialize(ref_list)
+  def deserialize(self, element, ref_list):
+    pass
   def copy(self, factory = None):
     result = (Element if factory is None else factory)(self.tag, self.attrib)
     result.text = self.text
@@ -215,14 +214,14 @@ def serialize_ref(value, ref_list):
 
 def deserialize_ref(value, ref_list):
   assert value is not None
-  return None if value < 0 else ref_list[value]
+  return None if value == -1 else ref_list[value]
 
 def serialize(value, fout, encoding = 'unicode'):
   ref_list = []
   serialize_ref(value, ref_list)
-  parents = [i for i in ref_list if not i.visited[2]]
+  todo = [i for i in ref_list if not i.visited[2]]
   root = xml.etree.ElementTree.Element('root')
-  root[:] = [i.visited[0] for i in parents]
+  root[:] = [i.visited[0] for i in todo]
   root.text = '\n  '
   for i in range(len(root) - 1):
     root[i].tail = '\n  '
@@ -230,38 +229,36 @@ def serialize(value, fout, encoding = 'unicode'):
   root.tail = '\n'
   xml.etree.ElementTree.ElementTree(root).write(fout, encoding)
   i = 0
-  while i < len(parents):
-    child = parents[i]
-    child.visited = None
-    parents.extend(child[:])
+  while i < len(todo):
+    node = todo[i]
+    node.visited = None
+    todo.extend(node[:])
     i += 1
 
 def deserialize(fin, factory = Element, encoding = 'unicode'):
-  root = xml.etree.ElementTree.parse(
-    fin,
-    xml.etree.ElementTree.XMLParser(
-      target = xml.etree.ElementTree.TreeBuilder(factory),
-      encoding = encoding
-    )
-  ).getroot()
+  root = xml.etree.ElementTree.parse(fin).getroot()
   assert root.tag == 'root'
-  for i in root:
-    i.tail = None
+  children = [factory(i.tag) for i in root]
+  todo = list(zip(root, children))
   i = 0
-  parents = root[:]
   ref_list = []
-  while i < len(parents):
-    j = parents[i]
-    if 'ref' in j.attrib:
-      ref = int(j.attrib['ref'])
-      del j.attrib['ref']
+  while i < len(todo):
+    element, node = todo[i]
+    ref = element.get('ref')
+    if ref is not None:
+      ref = int(ref)
       if len(ref_list) < ref + 1:
         ref_list.extend([None] * (ref + 1 - len(ref_list)))
-      ref_list[ref] = j
-    parents.extend(j[:])
+      ref_list[ref] = node
+    children = [factory(i.tag) for i in element]
+    node[:] = children
+    set_text(node, 0, '' if element.text is None else element.text)
+    for j in range(len(element)):
+      set_text(node, j + 1, '' if element[j].tail is None else element[j].tail)
+    todo.extend(zip(element, children))
     i += 1
-  for i in root:
-    i.deserialize(ref_list)
+  for element, node in todo:
+    node.deserialize(element, ref_list)
   return ref_list[0]
 
 # compatibility scheme to access arbitrary xml.etree.ElementTree.Element-like