Using the XmlDiffPatch Namespace

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.

Example 13-1. Program to construct and compare two XmlDocument instances
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.

Example 13-2. Program to patch an XML document
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>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.195.111