comparator.xml.labelA
Loading Editor...
comparator.xml.labelB
Loading Editor...

XML Compare — Find Every Difference Between Two XML Documents

XML changes quietly.

A SOAP service updates its response envelope. A Maven dependency gets bumped and the generated POM shifts three fields. An Android layout file gets auto-formatted by a different developer's IDE and the attribute order changes. A configuration file gets manually edited in production and nobody documents what changed.

You have two XML documents. Something is different. You need to know exactly what — not approximately, not "around line 47", but the exact element path, the exact attribute, the exact value that changed.

Paste both documents above. The comparator parses them structurally, ignores formatting noise, and reports every meaningful difference with its full XPath location. No scanning walls of angle brackets. No eyestrain. No missed changes.

The Unique Challenge of Comparing XML

XML comparison is harder than JSON comparison — and harder than text comparison — for reasons that are specific to how XML encodes information.

XML stores data in four different places simultaneously.

A single XML element can carry meaningful information in its tag name, its attributes, its text content, and its child elements — all at once:

<product id="SKU-001" category="electronics" available="true">
  <name lang="en">Wireless Headphones</name>
  <price currency="USD">79.99</price>
  <tags>
    <tag>audio</tag>
    <tag>bluetooth</tag>
  </tags>
</product>

A change to id, category, available, the text inside <name>, the lang attribute on <name>, the currency attribute on <price>, the numeric value of price, the number of <tag> elements, or their content — all are semantically meaningful differences. A text diff tool sees lines. An XML-aware comparator sees the semantic structure and reports changes precisely.

Attribute order is meaningless. Element order often isn't.

In XML, <book id="1" title="Dune"/> and <book title="Dune" id="1"/> are identical — attribute order carries no information. But <step>Mix ingredients</step><step>Bake</step> and <step>Bake</step><step>Mix ingredients</step> are semantically different — element order in sequences matters. Our comparator handles both correctly: attribute changes are detected regardless of order, and element ordering is tracked precisely.

Namespaces add a third layer of identity.

<soap:Body> and <s:Body> might be the same element — if both soap and s are prefixes bound to the same namespace URI. Or they might be completely different elements from different vocabularies. Namespace-aware XML comparison resolves namespace prefixes to their URIs before comparing, so prefix renaming doesn't produce false differences and true namespace mismatches aren't missed.

What Our XML Comparator Detects

Every comparison run reports differences across five distinct categories:

1Element Changes

Added elements, removed elements, and elements whose text content has changed — all reported with their full XPath path so you can locate them instantly:

/config/database/host Changed: "localhost" → "db.prod.example.com"
/config/features/feature[3] Added: <feature>dark-mode</feature>
/config/deprecated/timeout Removed

2Attribute Changes

Added attributes, removed attributes, and attributes whose values have changed — reported separately from element changes because they represent a structurally distinct type of modification:

/product/@available Changed: "true" → "false"
/product/price/@currency Removed
/product/@sku Added: "SKU-001-REV2"

3Namespace Changes

Changes to namespace declarations, namespace URI modifications, and prefix rebindings — reported with their scope (document-level vs element-level declarations):

/envelope Namespace changed: prefix 'soap' rebound
from http://schemas.xmlsoap.org/soap/envelope/
to http://www.w3.org/2003/05/soap-envelope

4Comment and Processing Instruction Changes

For use cases where XML comments or processing instructions carry meaningful content — documentation systems, transformation pipelines, or metadata-rich XML — changes to these constructs are tracked and reported.

5CDATA and Whitespace Handling

CDATA sections are compared by their decoded text content, not their encoding. <![CDATA[Hello & World]]> and Hello &amp; World are semantically equivalent text content and are treated identically. Insignificant whitespace is ignored by default.

XML Comparison Across Real Document Types

XML isn't one thing — it's a meta-format used to encode dozens of document vocabularies, each with its own structural conventions and comparison needs. Here's how XML diffing applies across the most common XML document types developers actually work with.

SOAP Web Services

SOAP messages are XML envelopes with a specific structure: EnvelopeHeader (optional) → Body → operation-specific payload. When a SOAP service behaves unexpectedly, comparing the request and response XML — or comparing responses from two versions of a service — is the fastest way to identify what changed.

<!-- SOAP Response - Before -->
<soap:Envelope xmlns:soap="..."> <soap:Body> <GetOrderResponse> <OrderStatus>PENDING</OrderStatus> <EstimatedDelivery>2024-01-20</EstimatedDelivery> </GetOrderResponse> </soap:Body> </soap:Envelope>
<!-- SOAP Response - After API Update -->
<soap:Envelope xmlns:soap="...">
<soap:Body>
<GetOrderResponse>
<OrderStatus>PROCESSING</OrderStatus>
<EstimatedDelivery>2024-01-20</EstimatedDelivery>
<TrackingNumber>1Z999AA10123456784</TrackingNumber>
</GetOrderResponse>
</soap:Body>
</soap:Envelope>

Diff result: OrderStatus changed from PENDING to PROCESSING. TrackingNumber element added. Two precise changes, instantly identified.

Maven POM Files

Maven's pom.xml defines the entire build configuration. Comparing POM files is essential for diagnosing build issues. Valid diffs: dependency version bumps, added/removed exclusions, plugin changes, and profile activation changes.

Android Layout & Manifest

XML-aware comparison cuts through the noise: attribute reordering is ignored (meaningless in Android layouts), and only genuine changes — added views, changed attributes, modified constraints — are reported.

Spring & Enterprise Java

The difference between two versions of a Spring config is often a single attribute or element that has major behavioral implications.

RSS and Atom Feeds

Comparing feed snapshots to detect what content has been added, updated, or removed since the last check. XML comparison surfaces these changes at the entry level.

SVG Files

Scalable Vector Graphics are XML. Comparing SVG outputs from different tools or versions of a graphics pipeline helps identify unintended changes to path data, style attributes, or element structure.

XML Diff in Your Toolchain — Programmatic Comparison

For automated, systematic XML comparison in CI/CD pipelines and test suites:

Java — XMLUnitStandard
import org.xmlunit.builder.DiffBuilder;
import org.xmlunit.diff.Diff;

Diff diff = DiffBuilder
    .compare(expectedXml)
    .withTest(actualXml)
    .ignoreWhitespace()
    .ignoreComments()
    .checkForSimilar()
    .build();

if (diff.hasDifferences()) {
    diff.getDifferences().forEach(d -> 
        System.out.println(d)
    );
}
Python — lxml + xmldiffpip install xmldiff
from xmldiff import main, formatting

# Get structural differences
diffs = main.diff_texts(
    xml_a.encode(), xml_b.encode()
)

# Or get a formatted patch
formatter = formatting.DiffFormatter()
result = main.diff_texts(
    xml_a.encode(),
    xml_b.encode(),
    formatter=formatter
)
print(result)
Command Line
# Compare two XML files directly
xmldiff file1.xml file2.xml

# Alternatively using xmllint + diff
# (sort attributes, normalize whitespace)
diff <(xmllint --c14n file1.xml) \
     <(xmllint --c14n file2.xml)
JavaScript — xml-jsdeep-diff
const xmljs = require('xml-js');
const { diff } = require('deep-diff');

const obj1 = xmljs.xml2js(xml1);
const obj2 = xmljs.xml2js(xml2);

// Compare parsed JS objects
const differences = diff(obj1, obj2);

Ignoring the Right Things — Noise vs Signal in XML Diffs

The most common frustration with XML comparison is too many reported differences — most of them noise that obscures the meaningful changes. Here's how to configure comparison to show only what matters:

1
Whitespace normalization

Insignificant whitespace between elements produces enormous text diffs but zero semantic differences. Our comparator ignores it by default. For mixed-content elements, you can override this.

2
Attribute order

Attribute order is semantically meaningless in XML. Our comparator never reports attribute reordering as a difference.

3
Comment content & Processing instructions

XML comments and instructions are non-semantic and often differ between versions. By default, they are excluded from comparison unless you explicitly need them.

4
Field/element exclusion

Specify element names or XPath expressions for elements that should be excluded from comparison: timestamps, generated IDs, session-specific values.

5
Namespace prefix normalization

Two documents can use different prefixes for the same namespace (soap: vs s:). Our comparator resolves prefixes to their namespace URIs before comparing.

Frequently Asked Questions

What makes XML comparison different from text comparison?

Text comparison compares raw character sequences — it's sensitive to formatting, attribute order, whitespace, and indentation. XML comparison parses both documents into their structural representation and compares semantics. Two XML documents with the same data but different attribute order, different indentation, or different namespace prefixes will show zero differences in XML comparison and potentially hundreds in text comparison. For XML, structural comparison is always more useful than text comparison.

Does attribute order matter when comparing XML?

No. The XML specification explicitly states that attribute order within an element is not significant. Our comparator treats <element a="1" b="2"/> and <element b="2" a="1"/> as identical. Only attribute value changes, additions, and removals are reported as differences.

How are XML namespaces handled in the comparison?

Namespace prefixes are resolved to their full namespace URIs before comparison. This means <soap:Body> and <s:Body> are treated as equivalent if both `soap` and `s` are bound to the same namespace URI, and as different if they're bound to different URIs. Namespace-aware comparison prevents false positives from prefix renaming and catches true namespace mismatches.

Can I compare very large XML files?

Yes. The comparator handles large files efficiently — use the file upload option for documents larger than a few hundred kilobytes for best performance. All processing runs in your browser.

Can I ignore specific elements in the comparison?

Yes. Use the element exclusion option to specify element names or XPath patterns that should be skipped during comparison — timestamps, generated IDs, session tokens, or any element whose value is expected to differ.

What is XPath and why does the comparator use it to report differences?

XPath (XML Path Language) is the standard way to address specific nodes in an XML document. Our comparator reports each difference with its full XPath location — `/order/items/item[2]/price` — so you can locate the exact element or attribute that changed without navigating through the document manually. XPath notation is unambiguous and works regardless of document formatting.

Does the comparator handle CDATA sections?

Yes. CDATA sections are compared by their decoded text content. <![CDATA[Hello & World]]> and Hello &amp; World represent the same text content and are treated as equivalent. Only genuine differences in the text content itself are reported.

What's the difference between "similar" and "identical" XML comparison?

Identical comparison requires exact structural and content matching. Similar comparison (as used in XMLUnit's checkForSimilar()) allows for some structural flexibility — element and attribute order differences that don't change meaning. Our tool uses structural semantic comparison by default, which falls between the two: semantically equivalent documents are treated as identical regardless of formatting, but structural differences are always reported.

Can I compare XML with different encodings?

The comparator normalizes encoding before comparison — UTF-8, UTF-16, and ISO-8859-1 encoded documents containing the same characters are treated as equivalent after decoding. If you're working with files in different encodings, paste the decoded text rather than the raw bytes.

How does the comparator handle mixed content?

Mixed content — elements that contain both text and child elements — is handled correctly. Text nodes between elements are compared as content, and whitespace in mixed-content elements is treated as significant (not ignored) to preserve the intended content structure.

Related Free Developer Tools

Same Structure. Different Data. Find It in Seconds.

Paste both XML documents above — SOAP envelopes, config files, Maven POMs, Android layouts, anything — and get a precise, structural diff with XPath locations for every difference found.