atif
atif

Reputation: 1147

Compare data of 2 xml files and output the difference

I have 2 xml files with same schema and I want to compare both the files to get only nodes which are present in 1st document but not in 2nd document and vise versa.

Case 1:

so my 1st xml is a.xml

<cases>
    <no sort="1">1</no>
    <no sort="2">2</no>
    <no sort="3">3</no>
    <no sort="4">4</no>
    <no sort="5">5</no>
    <no sort="6">6</no> 
</cases>

2nd xml is b.xml

<cases>
    <no sort="1">1</no>
    <no sort="2">2</no>
    <no sort="3">3</no>
    <no sort="4">4</no>
    <no sort="5">5</no>
    <no sort="6">6</no>
     <no sort="7">9</no>
 </cases>

Expected result after comparison should be

<cases>
       <no sort="7">9</no>
 </cases>

if <no sort="7">9</no> is in the a.xml and not in b.xml it should output the same result. So basically merging both document and remove nodes which are present in both documents.

I was thinking to loop through documents one by one and use xpath to check if the node is present is other document and if found discard it in the output. Any better solution to implement it in xslt 1.0 or xslt 2.0?

Upvotes: 1

Views: 4338

Answers (3)

Christophe
Christophe

Reputation: 2200

If I need to compare 2 XML files and see quickly the differences between them I sort the files using XSLT and then compare the two xml files manually by using WinMerge for example (a simple unix diff can also do the job). If you want to output the differences you can follow the method given by @keshlam

Here is the XSLT that sort my XML files :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes" encoding="UTF-8"/>

<xsl:template match="node()|@*">
    <xsl:copy>
            <xsl:apply-templates select="node()|@*">
                    <xsl:sort select="name()" />
                    <xsl:sort select="@*" />
                    <xsl:sort select="*" />
                    <xsl:sort select="text()" />
            </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Upvotes: 0

michael.hor257k
michael.hor257k

Reputation: 117003

How about this way (XSLT 1.0):

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:variable name="file2" select="document('b.xml')" />

<xsl:variable name="IDs1" select="/cases/no/@sort" />
<xsl:variable name="IDs2" select="$file2/cases/no/@sort" />

<xsl:template match="/cases">
<cases>
    <xsl:apply-templates select="no[not(@sort=$IDs2)]"/>
    <xsl:apply-templates select="$file2/cases/no[not(@sort=$IDs1)]"/>
</cases>
</xsl:template>

<xsl:template match="no">
    <xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>

You need to apply the stylesheet to your "a.xml " file and make sure "b.xml " is in the same directory.

Upvotes: 2

keshlam
keshlam

Reputation: 8058

If you websearch "xml diff", you'll find past versions of tools that compare XML documents and output their differences as an XML document See also https://stackoverflow.com/questions/1871076/are-there-any-free-xml-diff-merge-tools-available

Upvotes: 3

Related Questions