Example #1
0
    def _fmes_step2(self, tree1, tree2):
        """ the delete_node phase of the edit script algorithm

        instead of the standard algorithm, walk on tree1 in pre order and
        add a remove action on node not marked as mapped.
        Avoiding recursion on these node allow to extract remove on subtree
        instead of leaf

        do not use next_sibling for performance issue
        """
        stack = []
        i = 0
        node = tree1
        while node is not None:
            if node[N_MAPPED] != TRUE:
                if node[N_PARENT] and len(node[N_PARENT][N_CHILDS]) > i+1:
                    next_node = node[N_PARENT][N_CHILDS][i+1]
                    # if next node is a text node to remove, switch actions
                    if next_node[N_TYPE] == NT_TEXT and \
                       next_node[N_MAPPED] != TRUE:
                        self.add_action(['remove', f_xpath(next_node)])
                        delete_node(next_node)
                        try:
                            next_node = node[N_PARENT][N_CHILDS][i+1]
                        except:
                            next_node = None
                else:
                    next_node = None
                self.add_action(['remove', f_xpath(node)])
                delete_node(node)
                node = next_node
            elif node[N_CHILDS]:
                # push next sibbling on the stack
                if node[N_PARENT] and len(node[N_PARENT][N_CHILDS]) > i+1 :
                    stack.append((node[N_PARENT][N_CHILDS][i+1], i+1))
                node = node[N_CHILDS][0]
                i = 0
            elif node[N_PARENT] and len(node[N_PARENT][N_CHILDS]) > i+1:
                i += 1
                node = node[N_PARENT][N_CHILDS][i] #next_sibling(node)
            else:
                node = None
            if node is None and stack:
                node, i = stack.pop()
Example #2
0
    def _make_move(self, n1, n2, k):
        # avoid coalescing two text nodes
        act_node = self._before_delete_node(n1)
        if act_node is not None and act_node[0] is n2 and act_node[1] < k:
            k += 1
        if n1[N_TYPE] == NT_TEXT:
            k = self._before_insert_text(n2, n1, k)
        # avoid moving an attribute node on 
        elif n1[N_TYPE] == NT_ATTN: 
##             n2[N_NAME] = 'A@LogilabXmldiffTmpAttr:%s'%n2[N_NAME][2:]
##             n2[N_NAME] = '@LogilabXmldiffTmpAttr_%s'%n2[N_NAME]
##             n2[N_VALUE] = 'LogilabXmldiffTmpAttr_%s'%n2[N_VALUE]
##             self.add_action(['move-and-rename_node', n1, n2])
##             self.add_action(['rename_node', f_xpath(n2), n2[N_NAME][23:]])
            # avoid moving attribute node from a place to another on the same node
            if not n1[N_PARENT] is n2:
                self.add_action(['move', n1, n2])
        elif k <= nb_attrs(n2):
            self.add_action(['move-first', n1, n2])
        else:
            self.add_action(['move-after', n1, n2[N_CHILDS][k-1]])
        # real move
        delete_node(n1)
        insert_node(n2, n1, k)
Example #3
0
 def _fmes_step1(self, tree2, tree1):
     """ first step of the edit script algorithm
     combines the update, insert, align and move phases
     """
     mapping = self._mapping
     fp = self._find_pos
     al = self._align_children
     _partner = partner
     # x the current node in the breadth-first order traversal
     for x in make_bfo_list(tree2):
         y = x[N_PARENT]
         z = _partner(1, y)
         w = _partner(1, x)
         # insert
         if not w:
             todo = 1
             # avoid to add existing attribute node
             if x[N_TYPE] == NT_ATTN:
                 for n in z[N_CHILDS]:
                     if n[N_TYPE] != NT_ATTN:
                         break
                     elif n[N_VALUE] == x[N_VALUE]:
                         # FIXME: n should yet be mapped
                         todo = None
                         w = n
                         w[N_MAPPED] = TRUE
                         mapping.append((w, x))
                         delete_node(w[N_CHILDS][0])
                         break
             if todo is not None:
                 x[N_INORDER] = TRUE
                 k = fp(x)
                 # w = copy(x)
                 w = x[:]
                 w[N_CHILDS] = []
                 w.append(TRUE) # <-> w[N_MAPPED] = TRUE
                 mapping.append((w, x))
                 # avoid coalescing two text nodes
                 if w[N_TYPE] == NT_TEXT:
                     k = self._before_insert_text(z, w, k)
                 # real insert on tree 1
                 insert_node(z, w, k)
                 # make actions on subtree
                 self._dict[id(w)] = ww = w[:]
                 ww[N_CHILDS] = []
                 # preformat action
                 if not self._dict.has_key(id(z)):
                     if w[N_TYPE] == NT_ATTV:
                         action = ['update', f_xpath(z), w[N_VALUE]]
                     elif w[N_TYPE] == NT_ATTN:
                         action = ['append', f_xpath(z), ww]
                     elif z[N_TYPE] == NT_ROOT:
                         action = ['append-first', '/', ww]
                     else:
                         if ww[N_VALUE] == "spoken-languages":
                             self.test = ww
                         k = get_pos(w)
                         if k <= nb_attrs(z):
                             action = ['append-first', f_xpath(z), ww]
                         else:
                             action = ['insert-after', f_xpath(z[N_CHILDS][k-1]), ww]
                     self.add_action(action)
                 else:
                     insert_node(self._dict[id(z)], ww, k)
         elif x[N_NAME] != '/':
             v = w[N_PARENT]
             # update
             if w[N_VALUE] != x[N_VALUE]:
                 # format action
                 if w[N_TYPE] in (NT_NODE, NT_ATTN):
                     self.add_action(['rename', f_xpath(w), x[N_VALUE]])
                 else:
                     self.add_action(['update', f_xpath(w), x[N_VALUE]])
                 # real update on t1
                 w[N_VALUE] = x[N_VALUE]
                 # this is necessary for xpath
                 rename_node(w, x[N_NAME])
             # move x if parents not mapped together
             if not has_couple(v, y):
                 x[N_INORDER] = TRUE
                 k = fp(x)
                 self._make_move(w, z, k)
         # align children
         al(w, x)