def _add_xml_elements(self, root, data):
        """
        Implements to_xml() functionality in a recursive manner.

        :param root: Root XML element to add all created elements to.
        :param data: Data to convert to XML
        :return: The created XML node/element.
        """
        element = None

        for key, value in data.items():
            key = fix_schema_field_name(key)

            # Don't add empty items to the XML
            if value is colander.null or value is None or (isinstance(value, list) and len(value) == 0) or value is False or value == 'false':
                continue

            # If this is a group node for the purpose of displaying data nicely, ignore it and just add its children.
            if isinstance(value, dict):
                self._add_xml_elements(root, value)
            elif isinstance(value, list):
                element = etree.SubElement(root, key)
                for i in range(len(value)):
                    if value is not None:
                        child_element = etree.SubElement(element, key + ".%i" % i)
                        self._add_xml_elements(child_element, value[i])
                    else:
                        test = 1
            else:
                element = etree.SubElement(root, key)
                element.text = str(value)

        return element
    def convert_sqlalchemy_model_to_data(self, model, schema=None, force_not_empty_lists=False, dates_as_string=True,
                                         bool_false_as_none=True):
        """
        Functionality behind CAModel dictify(), this is a recursive function that will call itself for each child.

        :param model: Model to dictify.
        :param schema: Schema to dictify for (mainly used for recursive functionality).
        :param force_not_empty_lists: Ensure there is always at least 1 element in sequences/lists.
        :param dates_as_string: Output dates as objects or strings (deform widgets are inconsistent with this...)
        :return: Deform compatible appstruct for the passed in CAModel.
        """
        if schema is None:
            # This will not take groupings into account
            schema = convert_schema(SQLAlchemyMapping(type(model)))

        data = {}
    
        if model is None:
            return data
    
        for node in schema:
            name = fix_schema_field_name(node.name)
    
            if hasattr(model, name):
                value = getattr(model, name, None)

                if isinstance(value, basestring):
                    if isinstance(value, unicode):
                        value = value.encode("utf-8")
                    value = unicode(value, "utf-8")
    
                if isinstance(value, date) and dates_as_string:
                    value = str(value)
    
                if isinstance(value, bool):
                    if hasattr(node.widget, 'true_val') and value:
                        value = node.widget.true_val
                    else:
                        if bool_false_as_none:
                            value = None
                        elif hasattr(node.widget, 'false_val'):
                            value = node.widget.false_val
    
                if isinstance(value, list):
                    node_list = []

                    while node.widget is not None and len(value) < node.widget.min_len:
                        value.append(node.children[0]._reg.cls())

                    for item in value:
                        node_list.append(self.convert_sqlalchemy_model_to_data(item,  node.children[0], force_not_empty_lists, dates_as_string))

                    if force_not_empty_lists and len(value) == 0:
                        node_list.append(self.convert_sqlalchemy_model_to_data(node.children[0]._reg.cls(),  node.children[0], force_not_empty_lists, dates_as_string))
    
                    data[node.name] = node_list
#                elif isinstance(node.typ, deform.FileData) and value is not None:
#                    tempstore = node.widget.tmpstore.tempstore
#                    data[node.name] = node.default
#                    if value is not None:
#                        randid = value.split("/")[-1]
#                        for file_uid in tempstore:
#                            if 'randid' in tempstore[file_uid] and (tempstore[file_uid]['randid']) == str(randid):
#                                data[node.name] = tempstore[file_uid]
#                                break
    
                elif len(node.children):
                    data[node.name] = self.convert_sqlalchemy_model_to_data(value,  node, force_not_empty_lists, dates_as_string)
    
                elif value is None:
                    data[node.name] = node.default
                else:
                    if isinstance(node.widget, deform.widget.SelectWidget):
                        label = None
                        for select_value, select_label in node.widget.values:
                            if select_value == value:
                                label = select_label
                                break
                        # Give a best effor to set the redbox label fields that go along with all select fields
                        if hasattr(model, name + "_label"):
                            data[node.name + "_label"] = label

                    data[node.name] = value
            elif len(node.children) > 0:
                node_data = self.convert_sqlalchemy_model_to_data(model, node.children, force_not_empty_lists, dates_as_string)
    
                # Fix data for select mapping schemas
#                if not ':' in node.name:
#                    data['schema_select'] = str(getattr(model, 'method_id', None))

                data[node.name] = node_data
    
        return data
    def create_sqlalchemy_model(self, data, model_class=None, model_object=None):
        """
        Convert a deform appstruct into a CAModel object.

        :param data: Data to create the CAModel from.
        :param model_class: Optionally provide the model class (if the class isn't provided an object instance must be)
        :param model_object: Optionally provide the object instance (if the object isn't provided an class must be)
        :return: CAModel that has been created from the passed in data or None if the data caused no change.
        """
        is_data_empty = True
        if model_object is None and model_class is not None:
            model_object = model_class()

        if model_class is None and model_object is not None:
            model_class = self.get_model_class(model_object)

        if model_class is None or model_object is None:
            raise ValueError("Model class or model object could not be found while creating sqlalchemy model.")

        if data is None or not isinstance(data, dict) or len(data) <= 0:
            return None

        prefix = ''.join(str(x + ":") for x in data.items()[0][0].split(":")[:-1])
        new_model = True
        if model_object.id is not None and model_object.id >= 0:
            new_model = False
        elif prefix + 'id' in data and (isinstance(data[prefix + 'id'], (long, int)) or (isinstance(data[prefix + 'id'], basestring) and data[prefix + 'id'].isnumeric())) and long(data[prefix + 'id']) >= 0:
            new_model = False

        for field_name, value in data.items():
            field_name = fix_schema_field_name(field_name)

            # If this is a grouping - add its fields to the current model_object
            if not hasattr(model_object, field_name) and isinstance(value, dict): # NOTE: hasattr() WILL RETURN FALSE ON ANY EXCEPTION TO getattr() -> eg. wrong DB table fields.
                self.create_sqlalchemy_model(value, model_class=model_class, model_object=model_object)
            elif hasattr(model_object, field_name):
                # Fix form values to be the correct class and type and post formatting (eg. fileupload gets file handle from dict, bool is converted from 'false' to False, etc.).
                value = self.normalize_form_value(field_name, value, model_object)

                if isinstance(getattr(model_object, field_name), list) or isinstance(value, list):
                    # If the value hasn't changed
                    if value is None or value == getattr(model_object, field_name):
                        continue
                    # If all items have been removed
                    if value is None:
                        is_data_empty = False
                        setattr(model_object, field_name, [])
                        continue

                    # Otherwise the list has been changed in some other way
                    # Remove all items from the list, so that any items that aren't there are deleted.
                    old_items = []
                    for i in reversed(range(len(getattr(model_object, field_name, [])))):
                        old_items.append(getattr(model_object, field_name)[i])

                    for item in value:
                        if item is None or item is colander.null or not isinstance(item, dict) or len(item) <= 0:
                            continue

#                        if 'schema_select' in item and len(item) == 2:  # This is the custom developed select mapping - flatten the select out
#                            method = item.pop('schema_select')
#                            item = item.values()[0]

                        current_object = None

                        prefix = ''.join(str(x + ":") for x in item.items()[0][0].split(":")[:-1])

                        child_model_class=model_object._sa_class_manager[field_name].property.mapper.class_
                        unknown_model = False
                        # If the item has an id and the id==an item in the model_object, update the model object item instead of creating a new one.
                        if prefix + 'id' in item and (isinstance(item[prefix + 'id'], (long, int)) or (isinstance(item[prefix + 'id'], basestring) and item[prefix + 'id'].isnumeric())):
                            for model_item in old_items:
    #                            print "ID's: " + str(getattr(model_item, 'id', None)) + " : " + str(item['id'])
                                current_object_id = getattr(model_item, 'id', None)
    #                            print (isinstance(current_object_id, (int, long)) or (isinstance(current_object_id, basestring) and current_object_id.isnumeric()))
                                if (isinstance(current_object_id, (int, long)) or (isinstance(current_object_id, basestring) and current_object_id.isnumeric())) and int(getattr(model_item, 'id', None)) == int(item[prefix + 'id']):
                                    current_object = model_item
                                    old_items.remove(current_object)
    #                                print "Current Object: " + str(current_object)
                                    break

                            # If this is an object referenced from the database that the current model has no previous known state for.
                            if current_object is None:
                                current_object = self._sa_instance_state.session.query(child_model_class).filter_by(id=int(item[prefix + 'id'])).first()
                                unknown_model = True

                        if not unknown_model:
                            child_table_object = self.create_sqlalchemy_model(item, model_class=child_model_class, model_object=current_object)
                        else:
                            child_table_object = current_object
                            current_object = None

                        # If the child object has changed
                        if child_table_object is not None:
                            is_data_empty = False

                            # If the child object is new
                            if current_object is None:
                                getattr(model_object, field_name).append(child_table_object) # Add the modified object

                        # If the child object was just updated SQLAlchemy keeps track of the changes internally
#                        elif current_object is not None:
#                            getattr(model_object, field_name).append(current_object) # Re-add the un-modified object

                    # Delete items in the list that were missing from the new data
                    for item in old_items:
                        getattr(model_object, field_name).remove(item)
                        del item
                        is_data_empty = False

                elif isinstance(getattr(model_object, field_name), dict) or isinstance(value, dict):
                    # If the value hasn't been changed

                    if value == getattr(model_object, field_name):
                        continue
                    elif value is None:
                        # If the value is now empty and it was set previously
                        is_data_empty = False
                        setattr(model_object, field_name, None)
                        continue

                    current_object = None
                    if getattr(model_object, field_name) is not None:
                        current_object = getattr(model_object, field_name, None)

                    if not hasattr(model_object._sa_class_manager[field_name].property, 'mapper'):
                        raise AttributeError("Model conversion scripts have an error, trying to generate a model with invalid values.")
                    child_table_object = self.create_sqlalchemy_model(value, model_class=model_object._sa_class_manager[field_name].property.mapper.class_, model_object=current_object)

                    if child_table_object is not None:
                        setattr(model_object, field_name, child_table_object)
                        is_data_empty = False

                else:
                    # If the value hasn't been changed
                    field_type = self._get_field_type(field_name, model_object)
                    str(value)
                    str(getattr(model_object, field_name))
                    if str(value) == str(getattr(model_object, field_name)) or\
                       (field_type in (int, float, long) and (value is None or value==0) and (getattr(model_object, field_name) is None or getattr(model_object, field_name) == 0)):
                        continue

                    # If the value is now empty and it was set previously
                    elif value is None:
                        setattr(model_object, field_name, None)
                        is_data_empty = False
                        continue
                    try:

                        # Don't use default values to determine if the data is a new object.
                        ca_registry = self._get_ca_registry(field_name, model_class)
                        if ca_registry is None or ('default' not in ca_registry or not value == ca_registry['default'] or not new_model):
                            is_data_empty = False
                        setattr(model_object, field_name, value)

                    except Exception as e:
                        logger.exception("Failed to set model attribute: %s" % field_name)
                        continue


        if is_data_empty:
            return None

        return model_object