Use the xmldiff to perform this exact task.

main.py

from xmldiff import main
diff = main.diff_files("file1.xml", "file2.xml")
print(diff)

output

[DeleteNode(node='/ngs_sample/results/gastro_prelim_st/type[2]')]
Answer from Victor 'Chris' Cabral on Stack Overflow
🌐
PyPI
pypi.org › project › xmldiff
xmldiff · PyPI
A nice, easy to use Python API for using it as a library. Adds support for showing the diffs in different formats, mainly one where differences are marked up in the XML, useful for making human readable diffs.
      » pip install xmldiff
    
Published   May 13, 2024
Version   2.7.0
🌐
Readthedocs
xmldiff.readthedocs.io › en › stable › api.html
Python API — xmldiff documentation - Read the Docs
The “left”, “old” or “from” XML. The diff will show the changes to transform this XML to the “right” XML.
🌐
GitHub
github.com › JoshData › xml_diff
GitHub - JoshData/xml_diff: Compares two XML documents by diffing their text. · GitHub
This 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_diff · Then call the module from the command line: python3 -m xml_diff --tags del,ins doc1.xml doc2.xml > changes.xml ·
Starred by 44 users
Forked by 10 users
Languages   Python
🌐
GitHub
github.com › Shoobx › xmldiff
GitHub - Shoobx/xmldiff: A library and command line utility for diffing xml
A nice, easy to use Python API for using it as a library. Adds support for showing the diffs in different formats, mainly one where differences are marked up in the XML, useful for making human readable diffs.
Starred by 226 users
Forked by 53 users
Languages   Python 98.7% | Python 98.7%
🌐
Complianceascode
complianceascode.github.io › template › 2022 › 10 › 24 › xmldiff-unit-tests.html
Using xmldiff in Python unit tests - ComplianceAsCode Blog
October 24, 2022 - In the example above, we can see there are two differences between the two XML files. First is that the attribute idref on element described by XPath expression /ns0:Rule/ns0:platform[1] is changed to virtual. Second is that the text of the element described by XPath expression /ns0:Rule/ns0:ident[1] is changed to 777777. In a Python script, you can call xmldiff this way:
🌐
Read the Docs
media.readthedocs.org › pdf › xmldiff › latest › xmldiff.pdf pdf
xmldiff Documentation Lennart Regebro May 21, 2023
May 21, 2023 - This formatter return XML with tags describing the changes. These tags are designed so they easily can be changed · into something that will render nicely, for example with XSLT replacing the tags with the format you need. ... The default result of the diffing methods is to return an edit script, which is a list of Python objects called edit actions.
🌐
Readthedocs
xmldiff.readthedocs.io
xmldiff — xmldiff documentation
xmldiff is a library and a command-line utility for making diffs out of XML. This may seem like something that doesn’t need a dedicated utility, but change detection in hierarchical data is very different from change detection in flat data. XML type formats are also not only used for computer ...
Find elsewhere
🌐
PyPI
pypi.org › project › xml-diff
xml-diff · PyPI
Compares two XML documents by diffing their text, ignoring structure, and wraps changed text in / tags.
      » pip install xml-diff
    
Published   May 03, 2025
Version   0.7.1
Top answer
1 of 4
12

This is actually a reasonably challenging problem (due to what "difference" means often being in the eye of the beholder here, as there will be semantically "equivalent" information that you probably don't want marked as differences).

You could try using xmldiff, which is based on work in the paper Change Detection in Hierarchically Structured Information.

2 of 4
7

My approach to the problem was transforming each XML into a xml.etree.ElementTree and iterating through each of the layers. I also included the functionality to ignore a list of attributes while doing the comparison.

The first block of code holds the class used:

import xml.etree.ElementTree as ET
import logging

class XmlTree():

    def __init__(self):
        self.hdlr = logging.FileHandler('xml-comparison.log')
        self.formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')

    @staticmethod
    def convert_string_to_tree( xmlString):

        return ET.fromstring(xmlString)

    def xml_compare(self, x1, x2, excludes=[]):
        """
        Compares two xml etrees
        :param x1: the first tree
        :param x2: the second tree
        :param excludes: list of string of attributes to exclude from comparison
        :return:
            True if both files match
        """

        if x1.tag != x2.tag:
            self.logger.debug('Tags do not match: %s and %s' % (x1.tag, x2.tag))
            return False
        for name, value in x1.attrib.items():
            if not name in excludes:
                if x2.attrib.get(name) != value:
                    self.logger.debug('Attributes do not match: %s=%r, %s=%r'
                                 % (name, value, name, x2.attrib.get(name)))
                    return False
        for name in x2.attrib.keys():
            if not name in excludes:
                if name not in x1.attrib:
                    self.logger.debug('x2 has an attribute x1 is missing: %s'
                                 % name)
                    return False
        if not self.text_compare(x1.text, x2.text):
            self.logger.debug('text: %r != %r' % (x1.text, x2.text))
            return False
        if not self.text_compare(x1.tail, x2.tail):
            self.logger.debug('tail: %r != %r' % (x1.tail, x2.tail))
            return False
        cl1 = x1.getchildren()
        cl2 = x2.getchildren()
        if len(cl1) != len(cl2):
            self.logger.debug('children length differs, %i != %i'
                         % (len(cl1), len(cl2)))
            return False
        i = 0
        for c1, c2 in zip(cl1, cl2):
            i += 1
            if not c1.tag in excludes:
                if not self.xml_compare(c1, c2, excludes):
                    self.logger.debug('children %i do not match: %s'
                                 % (i, c1.tag))
                    return False
        return True

    def text_compare(self, t1, t2):
        """
        Compare two text strings
        :param t1: text one
        :param t2: text two
        :return:
            True if a match
        """
        if not t1 and not t2:
            return True
        if t1 == '*' or t2 == '*':
            return True
        return (t1 or '').strip() == (t2 or '').strip()

The second block of code holds a couple of XML examples and their comparison:

xml1 = "<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>"

xml2 = "<note><to>Tove</to><from>Daniel</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>"

tree1 = XmlTree.convert_string_to_tree(xml1)
tree2 = XmlTree.convert_string_to_tree(xml2)

comparator = XmlTree()

if comparator.xml_compare(tree1, tree2, ["from"]):
    print "XMLs match"
else:
    print "XMLs don't match"

Most of the credit for this code must be given to syawar

🌐
GitHub
gist.github.com › guillaumevincent › 74e5a9551ee14a774e5e
compare two XML in python · GitHub
compare two XML in python. GitHub Gist: instantly share code, notes, and snippets.
🌐
Inl
mooseframework.inl.gov › python › testers › XMLDiff.html
XMLDiff | MOOSE
XMLDiff tests compare XML output(s) for the test to a reference in the specified gold_dir folder.
🌐
GeeksforGeeks
geeksforgeeks.org › python › compare-two-xml-files-in-python
Compare Two Xml Files in Python - GeeksforGeeks
July 23, 2025 - We then convert these trees to their string representations using etree.tostring() and compare them. If the string representations are identical, it indicates that the XML files are the same; otherwise, they are considered different.
🌐
GitHub
github.com › joh › xmldiffs
GitHub - joh/xmldiffs: Compare two XML files, ignoring element and attribute order.
-o, --output - Name of the output file. Default value is minus sign, which prints the diff to the stdout. -x, --xml - instead of comparing two xml files, write sorted contents of FILE1 to FILE2.
Starred by 96 users
Forked by 27 users
Languages   Python 100.0% | Python 100.0%
🌐
GitHub
github.com › cfpb › xtdiff
GitHub - cfpb/xtdiff: :warning: THIS REPO IS DEPRECATED Python library to compare two XML trees and generate a set of actions that transform one into the other · GitHub
February 1, 2019 - >>> left = """<root> ... </root>""" >>> left_root = etree.fromstring(left) >>> right = """<root> ... <para>Lorem ipsum dolor sit amet</para> ... </root>""" >>> right_root = etree.fromstring(right) >>> actions = xtdiff.diff(left_root, right_root) >>> new_root = xtdiff.transform(left_tree, actions) >>> etree.tostring(new_root) <root> <para>Lorem ipsum dolor sit amet</para> </root>" xtdiff can also generate an XSL stylesheet that can be used to transform the left XML document into the right document.
Starred by 27 users
Forked by 6 users
Languages   Python
🌐
GitHub
github.com › Shoobx › xmldiff › blob › master › xmldiff › main.py
xmldiff/xmldiff/main.py at master · Shoobx/xmldiff
April 28, 2025 - from xmldiff import diff, formatting, patch · · __version__ = metadata.version("xmldiff") · FORMATTERS = { "diff": formatting.DiffFormatter, "xml": formatting.XMLFormatter, "old": formatting.XmlDiffFormatter, } ·
Author   Shoobx
🌐
openSUSE
software.opensuse.org › package › python-xmldiff
python-xmldiff
Python Tool for Detecting Differences Between XML Files · XMLdiff shows the differences between two similar XML files in the same way 'diff' does with text files. It can also be used as a library or as a command line tool and can work either with XML files or DOM trees.
🌐
Snyk
snyk.io › advisor › python packages › xmldiff
xmldiff - Python Package Health Analysis | Snyk
March 21, 2023 - Creates diffs of XML files. Visit Snyk Advisor to see a full health score report for xmldiff, including popularity, security, maintenance & community analysis. The python package xmldiff receives a total of 54,914 weekly downloads.