Compare lists to extract the changes

    :param old: old list
    :param new: new list
    :return: a dictionary with ``unchanged``, ``new``, ``deleted`` and ``sorted`` keys

    The sorted list is the union of unchanged and new lists, but keeping the original
    order from the new list.

def _diff_lists(old, new, comparator):
    '''
    Compare lists to extract the changes

    :param old: old list
    :param new: new list
    :return: a dictionary with ``unchanged``, ``new``, ``deleted`` and ``sorted`` keys

    The sorted list is the union of unchanged and new lists, but keeping the original
    order from the new list.
    '''
    def _remove_indent(node):
        '''
        Remove the XML indentation to compare XML trees more easily
        '''
        node_copy = copy.deepcopy(node)
        node_copy.text = None
        for item in node_copy.iter():
            item.tail = None
        return node_copy

    diff = {'unchanged': [], 'new': [], 'deleted': [], 'sorted': []}
    # We don't want to alter old since it may be used later by caller
    old_devices = copy.deepcopy(old)
    for new_item in new:
        found = [item for item in old_devices if comparator(_remove_indent(item), _remove_indent(new_item))]
        if found:
            old_devices.remove(found[0])
            diff['unchanged'].append(found[0])
            diff['sorted'].append(found[0])
        else:
            diff['new'].append(new_item)
            diff['sorted'].append(new_item)
    diff['deleted'] = old_devices
    return diff