Exemplo n.º 1
0
 def add_action(self, action):
     if len(action) > 2 and type(action[A_N2]) == types.ListType:
         if type(action[A_N1]) == types.ListType:
             #swap or move node
             action[A_N1] = f_xpath(action[A_N1])
             action[A_N2] = f_xpath(action[A_N2])
     AbstractFormatter.add_action(self, action)
Exemplo n.º 2
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()
Exemplo n.º 3
0
 def _before_insert_text(self, parent, new_text, k):
     """ check if a text node that will be remove has two sibbling text nodes
     to avoid coalescing two text nodes
     """
     if k > 1:
         if parent[N_CHILDS][k-1][N_TYPE] == NT_TEXT:
             tag = self.FAKE_TAG[:]
             self.add_action(['insert-after', f_xpath(parent[N_CHILDS][k-1]), tag])
             insert_node(parent, tag, k)
             return k+1
     if k < len(parent[N_CHILDS]):
         if parent[N_CHILDS][k][N_TYPE] == NT_TEXT:
             tag = self.FAKE_TAG[:]
             if k <= nb_attrs(parent):
                 self.add_action(['append_first', f_xpath(parent), tag])
             else:
                 self.add_action(['insert-after', f_xpath(parent[N_CHILDS][k]), tag])
             insert_node(parent, tag, k)                
     return k
Exemplo n.º 4
0
 def _before_delete_node(self, node):
     """ check if a text node will be inserted with a sibbling text node to
     avoid coalescing two text nodes
     """
     k = get_pos(node)
     parent = node[N_PARENT]
     if k >= 1 and k+1 < len(parent[N_CHILDS]):
         if parent[N_CHILDS][k-1][N_TYPE] == NT_TEXT and \
            parent[N_CHILDS][k+1][N_TYPE] == NT_TEXT:
             tag = self.FAKE_TAG[:]
             self.add_action(['insert-after', f_xpath(parent[N_CHILDS][k-1]), tag])
             insert_node(parent, tag, k)
             return parent, k
     return None
Exemplo n.º 5
0
 def add_action(self, action):
     if action[A_DESC] == 'move-first':
         # replace move-first with remove and insert (sibling nodes)
         self.edit_s.append(['remove', f_xpath(action[A_N1])])
         self.edit_s.append(['append', f_xpath(action[A_N2]), action[A_N1]])
     elif action[A_DESC] == 'move-after':
         # replace move-after with remove and insert (sibling nodes)
         self.edit_s.append(['remove', f_xpath(action[A_N1])])
         self.edit_s.append(['insert-after', f_xpath(action[A_N2]), action[A_N1]])
     elif action[A_DESC] == 'move-and-rename':
         # replace move-and-rename with remove and insert (sibling nodes)
         self.edit_s.append(['remove', f_xpath(action[A_N1])])
         self.edit_s.append(['insert-after', f_xpath(action[A_N2][N_PARENT]), action[A_N2]])
     elif action[A_DESC] == 'swap':
         # replace swap with remove and insert (sibling nodes)
         self.edit_s.append(['remove', f_xpath(action[A_N2])])
         self.edit_s.append(['insert-after', f_xpath(action[A_N1]), action[A_N2]])
     else:
         self.edit_s.append(action)
Exemplo n.º 6
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)