Package: xml_diff
Compares the text inside two XML documents and marks up the differences with<del>and<ins>tags.This is the result of about 7 years of trying to get this right and coded simply. I’ve used code like this in one form or another to compare bill text on GovTrack.us <https://www.govtrack.us>.The comparison is completely blind to the structure of the two XML documents. It does a word-by-word comparison on the text content only, and then it goes back into the original documents and wraps changed text in new<del>and<ins>wrapper elements.The documents are then concatenated to form a new document and the new document is printed on standard output. Or use this as a library and callcompareyourself with twolxml.etree.Elementnodes (the roots of your documents).The script is written in Python 3.ExampleComparing these two documents:<html>
        Here is <b>some bold</b> text.
</html>and:<html>
        Here is <i>some italic</i> content that shows how <tt>xml_diff</tt> works.
</html>Yields:<documents>
        <html>
                Here is <b>some <del>bold</del></b><del> text</del>.
        </html>
        <html>
                Here is <i>some <ins>italic</ins></i><ins> content that shows how </ins><tt><ins>xml_diff</ins></tt><ins> works</ins>.
        </html>
</documents>On Ubuntu, get dependencies with:apt-get install python3-lxml libxml2-dev libxslt1-devFor really fast comparisons, get Google’s Diff Match Patch library <https://code.google.com/p/google-diff-match-patch/>, as re-written and sped-up by @leutloff <https://github.com/leutloff/diff-match-patch-cpp-stl> and then turned into a Python extension module by me <https://github.com/JoshData/diff_match_patch-python>:pip3 install diff_match_patch_pythonOr if you can’t install that for any reason, use the pure-Python library:pip3 install diff-match-patchThis is also at <https://code.google.com/p/google-diff-match-patch/source/browse/trunk/python3/diff_match_patch.py>. xml_diff will use whichever is installed.Finally, install this module:pip3 install xml_diffThen call the module from the command line:python3 -m xml_diff  --tags del,ins doc1.xml doc2.xml > changes.xmlOr use the module from Python:import lxml.etree
from xml_diff import compare

dom1 = lxml.etree.parse("doc1.xml").getroot()
dom2 = lxml.etree.parse("doc2.xml").getroot()
comparison = compare(dom1, dom2)The two DOMs are modified in-place.Optional ArgumentsThecomparefunction takes other optional keyword arguments:mergeis a boolean (default false) that indicates whether the comparison function should perform a merge. If true,dom1will contain not just<del>nodes but also<ins>nodes and, similarly,dom2will contain not just<ins>nodes but also<del>nodes. Although the two DOMs will now contain the same semantic information about changes, and the same text content, each preserves their original structure — since the comparison is only over text and not structure. The newins/delnodes contain content from the other document (including whole subtrees), and so there’s no guarantee that the final documents will conform to any particular structural schema after this operation.word_separator_regex(defaultr"\s+|[^\s\w]") is a regular expression for how to separate words. The default splits on one or more spaces in a row and single instances of non-word characters.differis a function that takes two arguments(text1, text2)and returns an iterator over difference operations given as tuples of the form(operation, text_length), whereoperationis one of"="(no change in text),"+"(text inserted intotext2), or"-"(text deleted fromtext1). (See xml_diff/__init__.py’sdefault_differfunction for how the default differ works.)tagsis a two-tuple of tag names to use for deleted and inserted content. The default is('del', 'ins').make_tag_funcis a function that takes one argument, which is either"ins"or"del", and returns a newlxml.etree.Elementto be inserted into the DOM to wrap changed content. If given, thetagsargument is ignored.