[IMP] tools/convert: allow multiple root elements in view architectures (all fields...
[odoo/odoo.git] / bin / tools / convert.py
index 1ec4d22..a874951 100644 (file)
@@ -68,6 +68,24 @@ def _obj(pool, cr, uid, model_str, context=None):
     model = pool.get(model_str)
     return lambda x: model.browse(cr, uid, x, context=context)
 
+def _fix_multiple_roots(node):
+    """
+    Surround the children of the ``node`` element of an XML field with a
+    single root "data" element, to prevent having a document with multiple
+    roots once parsed separately.
+
+    XML nodes should have one root only, but we'd like to support
+    direct multiple roots in our partial documents (like inherited view architectures).
+    As a convention we'll surround multiple root with a container "data" element, to be
+    ignored later when parsing.
+    """
+
+    if len(node) > 1:
+        data_node = etree.Element("data")
+        for child in node:
+            data_node.append(child)
+        node.append(data_node)
+
 def _eval_xml(self, node, pool, cr, uid, idref, context=None):
     if context is None:
         context = {}
@@ -115,6 +133,7 @@ def _eval_xml(self, node, pool, cr, uid, idref, context=None):
                         if not id in idref:
                             idref[id]=self.id_get(cr, False, id)
                     return s % idref
+                _fix_multiple_roots(node)
                 return '<?xml version="1.0"?>\n'\
                     +_process("".join([etree.tostring(n, encoding='utf-8')
                                        for n in node]),
@@ -523,7 +542,9 @@ form: module.record_id""" % (xml_id,)
         m_l = map(escape, escape_re.split(rec.get("name",'').encode('utf8')))
 
         values = {'parent_id': False}
-        if rec.get('parent', False) is False:
+        if rec.get('parent', False) is False and len(m_l) > 1:
+            # No parent attribute specified and the menu name has several menu components, 
+            # try to determine the ID of the parent according to menu path
             pid = False
             res = None
             values['name'] = m_l[-1]
@@ -542,9 +563,13 @@ form: module.record_id""" % (xml_id,)
                     pid = self.pool.get('ir.ui.menu').create(cr, self.uid, {'parent_id' : pid, 'name' : menu_elem})
             values['parent_id'] = pid
         else:
+            # The parent attribute was specified, if non-empty determine its ID, otherwise
+            # explicitly make a top-level menu
             if rec.get('parent'):
                 menu_parent_id = self.id_get(cr, 'ir.ui.menu', rec.get('parent',''))
-            else: # we get here with <menuitem parent="">, explicit clear of parent
+            else:
+                # we get here with <menuitem parent="">, explicit clear of parent, or
+                # if no parent attribute at all but menu name is not a menu path
                 menu_parent_id = False
             values = {'parent_id': menu_parent_id}
             if rec.get('name'):
@@ -793,7 +818,9 @@ form: module.record_id""" % (xml_id,)
     def id_get(self, cr, model, id_str):
         if id_str in self.idref:
             return self.idref[id_str]
-        return self.model_id_get(cr, model, id_str)[1]
+        res = self.model_id_get(cr, model, id_str)
+        if res and len(res)>1: res = res[1]
+        return res
 
     def model_id_get(self, cr, model, id_str):
         model_data_obj = self.pool.get('ir.model.data')