docs: def import_template_xml(template_xml, allow_update=True, **kwargs):
      """
          Add the template, type and typeattrs described
          in an XML file.
  
          Delete type, typeattr entries in the DB that are not in the XML file
          The assumption is that they have been deleted and are no longer required.
      """
  
      template_xsd_path = config.get('templates', 'template_xsd_path')
      xmlschema_doc = etree.parse(template_xsd_path)
  
      xmlschema = etree.XMLSchema(xmlschema_doc)
  
      xml_tree = etree.fromstring(template_xml)
  
      xmlschema.assertValid(xml_tree)
  
      template_name = xml_tree.find('template_name').text
      template_description = xml_tree.find('template_description').text
  
      template_layout = None
      if xml_tree.find('layout') is not None and \
                 xml_tree.find('layout').text is not None:
          layout = xml_tree.find('layout')
          layout_string = get_etree_layout_as_dict(layout)
          template_layout = json.dumps(layout_string)
  
      try:
          tmpl_i = db.DBSession.query(Template).filter(Template.name==template_name).options(joinedload_all('templatetypes.typeattrs.attr')).one()
  
          if allow_update == False:
              raise HydraError("Existing Template Found with name %s"%(template_name,))
          else:
              log.debug("Existing template found. name=%s", template_name)
              tmpl_i.layout = template_layout
              tmpl_i.description = template_description
      except NoResultFound:
          log.debug("Template not found. Creating new one. name=%s", template_name)
          tmpl_i = Template(name=template_name, description=template_description, layout=template_layout)
          db.DBSession.add(tmpl_i)
  
      types = xml_tree.find('resources')
      #Delete any types which are in the DB but no longer in the XML file
      type_name_map = {r.name:r.id for r in tmpl_i.templatetypes}
      attr_name_map = {}
      for type_i in tmpl_i.templatetypes:
          for attr in type_i.typeattrs:
              attr_name_map[attr.attr.name] = (attr.id, attr.type_id)
  
      existing_types = set([r.name for r in tmpl_i.templatetypes])
  
      new_types = set([r.find('name').text for r in types.findall('resource')])
  
      types_to_delete = existing_types - new_types
  
      for type_to_delete in types_to_delete:
          type_id = type_name_map[type_to_delete]
          try:
              type_i = db.DBSession.query(TemplateType).filter(TemplateType.id==type_id).one()
              log.debug("Deleting type %s", type_i.name)
              db.DBSession.delete(type_i)
          except NoResultFound:
              pass
  
      #Add or update types.
      for resource in types.findall('resource'):
          type_name = resource.find('name').text
          #check if the type is already in the DB. If not, create a new one.
          type_is_new = False
          if type_name in existing_types:
              type_id = type_name_map[type_name]
              type_i = db.DBSession.query(TemplateType).filter(TemplateType.id==type_id).options(joinedload_all('typeattrs.attr')).one()
  
          else:
              log.debug("Type %s not found, creating new one.", type_name)
              type_i = TemplateType()
              type_i.name = type_name
              tmpl_i.templatetypes.append(type_i)
              type_is_new = True
  
          if resource.find('alias') is not None:
              type_i.alias = resource.find('alias').text
  
          if resource.find('description') is not None:
              type_i.description = resource.find('description').text
  
          if resource.find('type') is not None:
              type_i.resource_type = resource.find('type').text
  
          if resource.find('layout') is not None and \
              resource.find('layout').text is not None:
              layout = resource.find('layout')
              layout_string = get_etree_layout_as_dict(layout)
              type_i.layout = json.dumps(layout_string)
  
          #delete any TypeAttrs which are in the DB but not in the XML file
          existing_attrs = []
          if not type_is_new:
              for r in tmpl_i.templatetypes:
                  if r.name == type_name:
                      for typeattr in r.typeattrs:
                          existing_attrs.append(typeattr.attr.name)
  
          existing_attrs = set(existing_attrs)
  
          template_attrs = set([r.find('name').text for r in resource.findall('attribute')])
  
          attrs_to_delete = existing_attrs - template_attrs
          for attr_to_delete in attrs_to_delete:
              attr_id, type_id = attr_name_map[attr_to_delete]
              try:
                  attr_i = db.DBSession.query(TypeAttr).filter(TypeAttr.attr_id==attr_id, TypeAttr.type_id==type_id).options(joinedload_all('attr')).one()
                  db.DBSession.delete(attr_i)
                  log.debug("Attr %s in type %s deleted",attr_i.attr.name, attr_i.templatetype.name)
              except NoResultFound:
                  log.debug("Attr %s not found in type %s"%(attr_id, type_id))
                  continue
  
          #Add or update type typeattrs
          for attribute in resource.findall('attribute'):
              new_typeattr = parse_xml_typeattr(type_i, attribute)
  
      db.DBSession.flush()
  
      return tmpl_i