Thank you, but my problem was to merge by considering the attributes also. here is the code after my patch:
import sys from xml.etree import ElementTree as et class hashabledict(dict): def __hash__(self): return hash(tuple(sorted(self.items()))) class XMLCombiner(object): def __init__(self, filenames): assert len(filenames) > 0, 'No filenames!' # save all the roots, in order, to be processed later self.roots = [et.parse(f).getroot() for f in filenames] def combine(self): for r in self.roots[1:]: # combine each element with the first one, and update that self.combine_element(self.roots[0], r) # return the string representation return et.ElementTree(self.roots[0]) def combine_element(self, one, other):""" This function recursively updates either the text or the children of an element if another element is found in `one`, or adds it from `other` if not found.""" # Create a mapping from tag name to element, as that's what we are fltering with mapping = {(el.tag, hashabledict(el.attrib)): el for el in one} for el in other: if len(el) == 0: # Not nested try: # Update the text mapping[(el.tag, hashabledict(el.attrib))].text = el.text except KeyError: # An element with this name is not in the mapping mapping[(el.tag, hashabledict(el.attrib))] = el # Add it one.append(el) else: try: # Recursively process the element, and update it in the same way self.combine_element(mapping[(el.tag, hashabledict(el.attrib))], el) except KeyError: # Not in the mapping mapping[(el.tag, hashabledict(el.attrib))] = el # Just add it one.append(el)if __name__ == '__main__': r = XMLCombiner(sys.argv[1:-1]).combine() print '-'*20 print et.tostring(r.getroot()) r.write(sys.argv[-1], encoding="iso-8859-1", xml_declaration=True)