XML Diff: How to generate XML diff using XSLT? XML Diff: How to generate XML diff using XSLT? xml xml

XML Diff: How to generate XML diff using XSLT?


Interesting question! I once tried to do something similar involving two XML sources, and my experience was that there just ain't no way.

You could use XSL's facility for including user-built functions, and code up something really slick. But I really can't see it.

If I were to do something like this, I'd process the two XML files in parallel using DOM4J, which lets me easily traverse the code programmatically and do detail sub-queries.

Trying to do this in XSLT will either prove you to be a genius or drive you into madness.


XSLT is data-driven, that is, it goes through the single source XML file top to bottom looking for template matches in the XSL stylesheet. The templates don't really know where they are in the data, they just run their code when matched. You can reference another XML source, but the program will run according to the traversal of the original source.

So when you arrive at the nth child element of <blarg>, for example, you could look up the nth child of <blarg> in a second XML using the document() function. But the usefulness of this depends on the structure of your XML and what comparisons you're trying to do.

This behavior is opposite of most traditional scripts, which run through the program code top to bottom, calling on the data file when instructed. The latter--pull processing--is what you probably need to compare two XML sources. XSLT will break down in comparison as soon as there is a difference.


If what you mean by diff is something like checking whether items exist in one document (or node) but not another, you can use xpath key() function with a third parameter

<?xml version="1.0"?><xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs ="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xsl xs"><xsl:param name="doc2diff" required="yes"/><!-- docB is root node of the "second" document --><xsl:variable name="docB" select="document($doc2diff)"/><!-- docA is the root node of the first document --><xsl:variable name="docA" select="/"/><xsl:output method="xml" encoding="UTF-8" indent="yes"/><xsl:key name="items" match="Item" use="someId"/><xsl:template match="/"> <ListOfItems>  <In_A_NotIn_B>   <xsl:apply-templates select="Item">    <xsl:with-param name="otherDocument" select="$docB"/>   </xsl:apply-templates>  </In_A_NotIn_B>  <In_B_NotIn_A>   <xsl:apply-templates select="Item">    <xsl:with-param name="otherDocument" select="$docA"/>   </xsl:apply-templates>  </In_B_NotIn_A> </ListOfItems></xsl:template><xsl:template match="Item"> <xsl:param name="otherDocument"/>  <xsl:variable name="SOMEID" select="someId"/>  <xsl:if test="empty(key('items', $SOMEID, $otherDocument))">   <xsl:copy-of select="."/>  </xsl:if></xsl:template></xsl:stylesheet>`