Advertisement
Guest User

Untitled

a guest
Oct 21st, 2017
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.46 KB | None | 0 0
  1. import lxml.etree as etree
  2. from copy import deepcopy
  3.  
  4.  
  5. def create_delta_tree(changed_xml_tree, unchanged_xml_tree):
  6. deleted_elements_tree = create_one_operation_type_element_tree(unchanged_xml_tree, changed_xml_tree,
  7. get_elements_to_be_deleted)
  8. created_elements_tree = create_one_operation_type_element_tree(changed_xml_tree, unchanged_xml_tree,
  9. get_elements_to_be_created)
  10. updated_elements_tree = create_one_operation_type_element_tree(changed_xml_tree, unchanged_xml_tree,
  11. get_elements_to_be_updated)
  12. delta_tree = merge_to_one_tree(deleted_elements_tree, created_elements_tree, updated_elements_tree)
  13. return delta_tree
  14.  
  15.  
  16. def create_one_operation_type_element_tree(base_tree, reference_tree, elements_filter):
  17. changeable_btree = deepcopy(base_tree)
  18. changeable_rtree = deepcopy(reference_tree)
  19. get_updated_elements(changeable_btree.getroot()[0], changeable_rtree.getroot()[0], elements_filter)
  20. return changeable_btree
  21.  
  22.  
  23. def get_updated_elements(base_element, reference_element, function_filtering_elements):
  24. e1_children_names = create_distinct_names_dict(base_element.getchildren())
  25. e2_children_names = create_distinct_names_dict(reference_element.getchildren())
  26.  
  27. children_to_be_left = function_filtering_elements(e1_children_names, e2_children_names)
  28. remove_child_elements(base_element, children_to_be_left)
  29. return len(children_to_be_left) > 0
  30.  
  31.  
  32. def create_distinct_names_dict(elements):
  33. return {create_distinct_name(element): element for element in elements}
  34.  
  35.  
  36. def create_distinct_name(element):
  37. distinct_name = element.tag
  38. attribs = element.attrib
  39. if attribs:
  40. distinct_name += ''.join(attribs.values())
  41. return distinct_name
  42.  
  43.  
  44. def remove_child_elements(element, children_to_be_left):
  45. for child in element.getchildren():
  46. remove_or_leave(child, children_to_be_left)
  47.  
  48.  
  49. def remove_or_leave(child, to_be_left):
  50. if create_distinct_name(child) not in to_be_left:
  51. child.getparent().remove(child)
  52.  
  53.  
  54. def xml_compare(x1, x2, reporter=None):
  55. try:
  56. if x1.tag != x2.tag:
  57. if reporter:
  58. reporter('Tags do not match: %s and %s' % (x1.tag, x2.tag))
  59. return False
  60. for name, value in x1.attrib.items():
  61. if x2.attrib.get(name) != value:
  62. if reporter:
  63. reporter('Attributes do not match: %s=%r, %s=%r'
  64. % (name, value, name, x2.attrib.get(name)))
  65. return False
  66. for name in x2.attrib.keys():
  67. if name not in x1.attrib:
  68. if reporter:
  69. reporter('x2 has an attribute x1 is missing: %s'
  70. % name)
  71. return False
  72. if not x1.text == x2.text:
  73. if (x1.text and x1.text.strip()) and (x2.text and x2.text.strip()):
  74. if reporter:
  75. reporter('text: %r != %r' % (x1.text, x2.text))
  76. return False
  77. return True
  78. except SyntaxError:
  79. return False
  80.  
  81.  
  82. def get_elements_to_be_deleted(e1_cn, e2_cn):
  83. to_be_deleted = []
  84. for dist_name, element in e1_cn.items():
  85. find_elements_to_be_deleted(dist_name, e2_cn, element, to_be_deleted=to_be_deleted)
  86. return to_be_deleted
  87.  
  88.  
  89. def find_elements_to_be_deleted(dist_name, e2_cn, element, to_be_deleted):
  90. if dist_name not in e2_cn.keys():
  91. to_be_deleted.append(dist_name)
  92. remove_child_elements(element, [])
  93. element.text = None
  94. else:
  95. get_updated_elements(element, e2_cn[dist_name], get_elements_to_be_deleted)
  96.  
  97.  
  98. def get_elements_to_be_created(e1_cn, e2_cn):
  99. to_be_created = []
  100. for dist_name, element in e1_cn.items():
  101. find_elements_to_be_created(dist_name, e2_cn, element, to_be_created=to_be_created)
  102. return to_be_created
  103.  
  104.  
  105. def find_elements_to_be_created(dist_name, e2_cn, element, to_be_created):
  106. if dist_name not in e2_cn.keys():
  107. to_be_created.append(dist_name)
  108. else:
  109. get_updated_elements(element, e2_cn[dist_name], get_elements_to_be_created)
  110.  
  111.  
  112. def get_elements_to_be_updated(e1_cn, e2_cn):
  113. to_be_updated = []
  114. for dist_name, element in e1_cn.items():
  115. find_elements_to_be_updated(dist_name, e2_cn, element, to_be_updated=to_be_updated)
  116. return to_be_updated
  117.  
  118.  
  119. def find_elements_to_be_updated(dist_name, e2_cn, element, to_be_updated):
  120. if dist_name in e2_cn.keys():
  121. if get_updated_elements(element, e2_cn[dist_name], get_elements_to_be_updated) or not xml_compare(element,
  122. e2_cn[
  123. dist_name]):
  124. to_be_updated.append(dist_name)
  125.  
  126.  
  127. def merge_to_one_tree(del_elem_tree, cre_elem_tree, upd_elem_tree):
  128. non_empty_trees = []
  129. for elem_tree, operation in zip([del_elem_tree, cre_elem_tree, upd_elem_tree], ['delete', 'create', 'update']):
  130. append_tree_if_not_empty(elem_tree, operation, non_empty_trees=non_empty_trees)
  131. for tree in non_empty_trees[1:]:
  132. move_all_elements_to_first_tree(non_empty_trees, tree)
  133. return non_empty_trees[0]
  134.  
  135.  
  136. def append_tree_if_not_empty(elem_tree, operation, non_empty_trees):
  137. if len(elem_tree.getroot()) > 0:
  138. remove_header(elem_tree)
  139. change_elements_operation(elem_tree, operation)
  140. non_empty_trees.append(elem_tree)
  141.  
  142.  
  143. def remove_header(tree):
  144. for child in tree.getroot()[0]:
  145. if child.tag == 'header':
  146. child.getparent().remove(child)
  147.  
  148.  
  149. def change_elements_operation(tree, operation):
  150. for child in tree.getroot()[0]:
  151. child.attrib['operation'] = operation
  152.  
  153.  
  154. def move_all_elements_to_first_tree(non_empty_trees, tree):
  155. for element in tree.getroot()[0]:
  156. non_empty_trees[0].getroot()[0].append(element)
  157.  
  158.  
  159. if __name__ == '__main__':
  160. xml_tree = etree.parse(r'2_cells_to_delta.xml')
  161. dwojeczka = etree.parse(r'3_cells_to_delta.xml')
  162.  
  163. # get_updated_elements(xml_tree.getroot()[0], dwojeczka.getroot()[0], get_elements_to_be_deleted)
  164. # print(etree.tostring(xml_tree))
  165. print(etree.tostring(create_delta_tree(xml_tree, dwojeczka)))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement