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()
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)
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)