[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: Is XSLT a suitable solution for generating a diff
Sometime back, I posted a stylesheet to test "two XML documents for equality" .. Below is the stylesheet. It just displays whether two XML documents are Equal or Not Equal. It does not display what all and where the differences are.. This stylesheet is not namespace aware. I think you can take some help from this! There are also some solutions listed at http://www.dpawson.co.uk/xsl/sect2/N1777.html <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="text" /> <!-- parameter for "ignoring white-space only text nodes" during comparison --> <!-- if iws='y', "white-space only text nodes" will not be considered during comparison --> <xsl:param name="iws" /> <xsl:variable name="doc1" select="document('file1.xml')" /> <xsl:variable name="doc2" select="document('file2.xml')" /> <xsl:template match="/"> <!-- store hash of 1st document into a variable; it is concatination of name and values of all nodes --> <xsl:variable name="one"> <xsl:for-each select="$doc1//@*"> <xsl:sort select="name()" /> <xsl:variable name="expr"> <xsl:call-template name="constructXPathExpr"> <xsl:with-param name="node" select=".." /> <xsl:with-param name="xpath" select="name(..)" /> </xsl:call-template> </xsl:variable> <xsl:value-of select="concat($expr,'/@',name(),':',.)" />:<xsl:value-of select="count(../ancestor-or-self::node() | ../preceding::node())" /> </xsl:for-each> <xsl:choose> <xsl:when test="$iws='y'"> <xsl:for-each select="$doc1//node()[not(normalize-space(self::text()) = '')]"> <xsl:variable name="expr"> <xsl:call-template name="constructXPathExpr"> <xsl:with-param name="node" select="ancestor-or-self::*[1]" /> <xsl:with-param name="xpath" select="name(ancestor-or-self::*[1])" /> </xsl:call-template> </xsl:variable> <xsl:value-of select="concat($expr,'/',name(),':',.)" />:<xsl:value-of select="count(ancestor-or-self::node() | preceding::node())" /> </xsl:for-each> </xsl:when> <xsl:otherwise> <xsl:for-each select="$doc1//node()"> <xsl:variable name="expr"> <xsl:call-template name="constructXPathExpr"> <xsl:with-param name="node" select="ancestor-or-self::*[1]" /> <xsl:with-param name="xpath" select="name(ancestor-or-self::*[1])" /> </xsl:call-template> </xsl:variable> <xsl:value-of select="concat($expr,'/',name(),':',.)" />:<xsl:value-of select="count(ancestor-or-self::node() | preceding::node())" /> </xsl:for-each> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- store hash of 2nd document into a variable; it is concatination of name and values of all nodes --> <xsl:variable name="two"> <xsl:for-each select="$doc2//@*"> <xsl:sort select="name()" /> <xsl:variable name="expr"> <xsl:call-template name="constructXPathExpr"> <xsl:with-param name="node" select=".." /> <xsl:with-param name="xpath" select="name(..)" /> </xsl:call-template> </xsl:variable> <xsl:value-of select="concat($expr,'/@',name(),':',.)" />:<xsl:value-of select="count(../ancestor-or-self::node() | ../preceding::node())" /> </xsl:for-each> <xsl:choose> <xsl:when test="$iws='y'"> <xsl:for-each select="$doc2//node()[not(normalize-space(self::text()) = '')]"> <xsl:variable name="expr"> <xsl:call-template name="constructXPathExpr"> <xsl:with-param name="node" select="ancestor-or-self::*[1]" /> <xsl:with-param name="xpath" select="name(ancestor-or-self::*[1])" /> </xsl:call-template> </xsl:variable> <xsl:value-of select="concat($expr,'/',name(),':',.)" />:<xsl:value-of select="count(ancestor-or-self::node() | preceding::node())" /> </xsl:for-each> </xsl:when> <xsl:otherwise> <xsl:for-each select="$doc2//node()"> <xsl:variable name="expr"> <xsl:call-template name="constructXPathExpr"> <xsl:with-param name="node" select="ancestor-or-self::*[1]" /> <xsl:with-param name="xpath" select="name(ancestor-or-self::*[1])" /> </xsl:call-template> </xsl:variable> <xsl:value-of select="concat($expr,'/',name(),':',.)" />:<xsl:value-of select="count(ancestor-or-self::node() | preceding::node())" /> </xsl:for-each> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="$one = $two"> Equal </xsl:when> <xsl:otherwise> Not equal </xsl:otherwise> </xsl:choose> </xsl:template> <!-- a template to construct an XPath expression, for a given element node --> <xsl:template name="constructXPathExpr"> <xsl:param name="node" /> <xsl:param name="xpath" /> <xsl:choose> <xsl:when test="$node/parent::*"> <xsl:call-template name="constructXPathExpr"> <xsl:with-param name="node" select="$node/parent::*" /> <xsl:with-param name="xpath" select="concat(name($node/parent::*),'/',$xpath)" /> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat('/',$xpath)" /> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> Also, XSLT may not be the suitable way to extract the changes (in general to do software change management). Probably, you must use an off-the-shelf tool like VSS or "Clear Case" .. These tools give us robust set of facility.. Regards, Mukul --- cknell@xxxxxxxxxx wrote: > I have been considering a change management tool for > comparing versions of an XML document. I have > searched and haven't been able to find anything on > point so I'm posting this question to the list. > Given two versions of an XML document (say we are > working with a document valid per a DTD or schema), > is XSLT a suitable way of extracting the changes > between versions of the document, and if so, can > anyone show me a general method of writing a > suitable stylesheet? Thanks. > > -- > Charles Knell > cknell@xxxxxxxxxx - email > > Yahoo! Mail Stay connected, organized, and protected. Take the tour: http://tour.mail.yahoo.com/mailtour.html
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|