def traverse(self, callback):
        ''' Traverse through all keys and values (in-order)
            and replace keys and values with the return values
            from the callback function.
        '''
        def _traverse_node(path, node, callback):
            ret_val = callback(path, node)
            if ret_val is not None:
                # replace node with the return value
                node = ret_val
            else:
                # traverse deep into the hierarchy
                if isinstance(node, YAMLDict):
                    for k, v in node.items():
                        node[k] = _traverse_node(path + [k], v,
                                                 callback)
                elif isinstance(node, list):
                    for i, v in enumerate(node):
                        node[i] = _traverse_node(path + ['[{0}]'.format(i)], v,
                                                 callback)
                else:
                    pass
            return node
        _traverse_node([], self, callback)