Since XmlDiffPatch
is a
.NET assembly, it can be included in any .NET project by adding it as
a reference in Visual Studio .NET, or by specifying the
/r:xmldiffpatch.dll
command-line switch to the C#
compiler. If you plan to use XmlDiffPatch
in
multiple projects, you may find it useful to add it to your Global
Assembly Cache using the installutil
executable or the Microsoft .NET Framework Configuration
tool.
Once
you’ve added the XmlDiffPatch
reference to your project or Makefile, you can include it in your own
source code with the using statement:
using Microsoft.XmlDiffPatch;
Example 13-1 shows a program which constructs two
XmlDocument
instances in memory, then compares
them using XmlDiff
.
using System; using System.Text; using System.Xml; using Microsoft.XmlDiffPatch; public class DoDiff { public static void Main(string [ ] args) { XmlDocument doc1 = new XmlDocument( ); doc1.AppendChild(doc1.CreateXmlDeclaration("1.0", null, null)); doc1.AppendChild(doc1.CreateElement("foo")); XmlDocument doc2 = new XmlDocument( ); doc2.AppendChild(doc2.CreateXmlDeclaration("1.0", null, null)); doc2.AppendChild(doc2.CreateElement("bar")); doc2.DocumentElement.AppendChild(doc2.CreateElement("baz")); XmlTextWriter diffgram = new XmlTextWriter(Console.Out); diffgram.Formatting = Formatting.Indented; XmlDiff diff = new XmlDiff(XmlDiffOptions.None); diff.Compare(doc1, doc2, diffgram); diffgram.Flush( ); } }
This program simply creates two
XmlDocument
instances, with one element each. The
original document’s root element is named
foo
, and the modified document’s
root element is named bar
. The modified
document’s bar
element is then
given a child element named baz
. The program then
creates an instance of the XmlDiff
class and calls
its Compare( )
method, which sends the following
output to the console. Note that I’ve formatted it
for readability:
<?xml version="1.0" encoding="IBM437"?> <xd:xmldiff version="1.0" srcDocHash="1260031300178880892" options="None" fragments="no" xmlns:xd="http://schemas.microsoft.com/xmltools/2002/xmldiff"> <xd:node match="1" /> <xd:remove match="2" subtree="no" /> <xd:add type="1" name="bar"> <xd:add type="1" name="baz" /> </xd:add> </xd:xmldiff>
The XmlDiff
constructor has an XmlDiffOptions
parameter which
can be used to specify that certain information should be ignored
while computing the difference. Things to be ignored can include the
order of child nodes, comments, DTDs, XML declarations, processing
instructions, XML namespaces and namespace prefixes, and whitespace.
Compare( )
has six overloads to deal with the
various types of inputs, including URI, XmlNode
,
and XmlReader
. It is also capable of dealing with
non-well-formed XML fragments and partial documents. The overload of
Compare( )
which I’ve used here
takes two XmlNode
instances as input and sends the
output to an XmlWriter
. The output is an XML Diff
Language (XDL) Diffgram, about which I’ll talk more
in a minute.
Once you’ve run Compare( )
and
written the XDL Diffgram to an XmlWriter
, you can
use XmlPatch
to apply the Diffgram to the original
XML document, and duplicate the changes necessary to produce the
modified document.
Example 13-2 shows modifications to the original program to patch the original XML document. The changes are highlighted.
using System; using System.IO; using System.Text; using System.Xml; using Microsoft.XmlDiffPatch; public class DoDiff { public static void Main(string [ ] args) { XmlDocument doc1 = new XmlDocument( ); doc1.AppendChild(doc1.CreateXmlDeclaration("1.0", null, null)); doc1.AppendChild(doc1.CreateElement("foo")); XmlDocument doc2 = new XmlDocument( ); doc2.AppendChild(doc2.CreateXmlDeclaration("1.0", null, null)); doc2.AppendChild(doc2.CreateElement("bar")); doc2.DocumentElement.AppendChild(doc2.CreateElement("baz")); Stream stream = new MemoryStream( ); XmlTextWriter diffgram = new XmlTextWriter(new StreamWriter(stream)); diffgram.Formatting = Formatting.Indented; XmlDiff diff = new XmlDiff(XmlDiffOptions.None); diff.Compare(doc1, doc2, diffgram); stream.Seek(0, SeekOrigin.Begin); XmlPatch patch = new XmlPatch( ); patch.Patch(doc1, new XmlTextReader(stream)); XmlTextWriter writer = new XmlTextWriter(Console.Out); writer.Formatting = Formatting.Indented; doc1.WriteTo(writer); } }
In the first group of highlighted lines,
the Diffgram is written to an XmlTextWriter
which
wraps a MemoryStream
instead of to the console.
Then the MemoryStream
is reset back to the
beginning, and a new XmlPatch
instance is created.
The XmlPatch.Patch( )
method is called to patch
the doc1
XmlDocument
according
to the Diffgram. Finally, the patched doc1
is
written to the console with an XmlTextWriter
.
The output from the modified program is below. It should look just
the same as doc2
would have looked if it were
serialized to the console:
<?xml version="1.0"?> <bar> <baz /> </bar>
18.117.7.131