xmldiffreport¶
N-way structural & semantic XML diff that produces human-readable Markdown reports — driven by per-dialect recipes.
xmldiffreport compares two or more XML files at once — BMC Control-M
exports, Maven POMs, JUnit/xUnit reports, sitemaps, or any dialect you
teach it with a small recipe — and tells you what actually changed, element by
element and attribute by attribute, instead of a noisy line-by-line text diff. It aligns elements by a natural key (not by
position), ignores volatile attributes, and writes a clean Markdown
report.
It started as a way to spot differences between BMC Control-M job patches
flowing through test → uat → bench → prod, and generalized into a recipe-driven
engine that works on any XML dialect (Control-M exports, Maven POMs, JUnit
reports, sitemaps, …).
Quickstart¶
# Compare two (or more) XML files — uses the generic recipe by default
xmldiffreport old.xml new.xml -o report.md
Working with a known dialect (Control-M, sitemaps, …)? Add --recipe. Pass
directories to compare every *.xml inside them. See
Getting Started and Inputs & file layout.
from xmldiffreport import diff
result = diff(["old.xml", "new.xml"], recipe="sitemap") # a file, files, or dir(s)
print(result.render()) # Markdown — or .render("html")
Why not a plain diff?¶
A text diff on XML lies — volatile attributes (VERSION, CREATION_TIME,
JOBISN), reordered children, and attribute order all create false changes.
xmldiffreport is structural, N-way (3+ files at once), and emits a
review-ready report.
| xmldiffreport | xmldiff |
DiffDog / Oxygen | DeltaXML | |
|---|---|---|---|---|
| Match by declared natural key | ✅ | ❌ | ⚠️ limited | ✅ |
| N-way (3+ files) | ✅ | ❌ | ❌ | ❌ |
| Markdown report out of the box | ✅ | ❌ | ⚠️ GUI | ❌ |
| Open source | ✅ | ✅ | ❌ | ❌ |
Next steps¶
- Getting Started — install and run your first diff.
- How it works — the engine model and what gets reported.
- Writing recipes — teach it a new XML dialect.
- Usage harness — run it on your own environment folders.
- API Reference — the library API.