Export (0) Print
Expand All

Extending the DOM

The Microsoft .NET Framework includes a base set of classes that provides an implementation of the XML Document Object Model (DOM). The XmlNode, and its derived classes, provides methods and properties that allow you to navigate, query, and modify the content and structure of an XML document.

When XML content is loaded into memory using the DOM, the nodes created contain information such as node name, node type, and so on. There may be occasions where you require specific node information that the base classes do not provide. For example, you may want to see the line number and position of the node. In this case, you can derive new classes from the existing DOM classes and add additional functionality.

There are two general guidelines when deriving new classes:

  • It is recommended that you never derive from the XmlNode class. Instead, it is recommended that you derive classes from the class corresponding to the node type that you are interested in. For example, if you want to return additional information on attribute nodes, you can derive from the XmlAttribute class.

  • Except for the node creation methods, it is recommended that when overriding a function, you should always call the base version of the function and then add any additional processing.

The XmlDocument class contains node creation methods. When an XML file is loaded, these methods are called to create the nodes. You can override these methods so that your node instances are created when a document is loaded. For example, if you have extended the XmlElement class, you would inherit the XmlDocument class and override the CreateElement method.

The following example shows how to override the CreateElement method to return your implementation of the XmlElement class.

class LineInfoDocument : XmlDocument {
  public override XmlElement CreateElement(string prefix, string localname, string nsURI) {
  LineInfoElement elem = new LineInfoElement(prefix, localname, nsURI, this);
  return elem;
  }

To extend a class, derive your class from one of the existing DOM classes. You can then override any of the virtual methods or properties in the base class, or add your own.

In the following example, a new class is created, which implements the XmlElement class and the IXmlLineInfo interface. Additional methods and properties are defined which allows users to gather line information.

class LineInfoElement : XmlElement, IXmlLineInfo {
   int lineNumber = 0;
   int linePosition = 0;
   internal LineInfoElement( string prefix, string localname, string nsURI, XmlDocument doc ) : base( prefix, localname, nsURI, doc ) {
       ( (LineInfoDocument)doc ).IncrementElementCount();
  }   
  public void SetLineInfo( int linenum, int linepos ) {
      lineNumber = linenum;
      linePosition = linepos;
  }
  public int LineNumber {
     get {
       return lineNumber;
     }
  }
  public int LinePosition {
      get {
        return linePosition;
      }
  }
  public bool HasLineInfo() { 
    return true; 
  }
} // End LineInfoElement class.

The following example counts the number of elements in an XML document.

using System;
using System.Xml;
using System.IO;

class LineInfoDocument : XmlDocument {

  int elementCount;
  internal LineInfoDocument():base() {
    elementCount = 0;
  }

  public override XmlElement CreateElement( string prefix, string localname, string nsURI) {
    LineInfoElement elem = new LineInfoElement(prefix, localname, nsURI, this );
    return elem;
  }

  public void IncrementElementCount() {
     elementCount++;
  }

  public int GetCount() {
     return elementCount;
  }
} // End LineInfoDocument class.

 
class LineInfoElement:XmlElement {

    internal LineInfoElement( string prefix, string localname, string nsURI, XmlDocument doc ):base( prefix,localname,nsURI, doc ){
      ((LineInfoDocument)doc).IncrementElementCount();
    }   
} // End LineInfoElement class. 

 
public class Test {

  const String filename = "book.xml";
  public static void Main() {

     LineInfoDocument doc =new LineInfoDocument();
     doc.Load(filename);    
     Console.WriteLine("Number of elements in {0}: {1}", filename, doc.GetCount());

  }
} 

book.xml

<!--sample XML fragment-->
<book genre='novel' ISBN='1-861001-57-5' misc='sale-item'>
  <title>The Handmaid's Tale</title>
  <price>14.95</price>
</book>

Number of elements in book.xml: 3

For an example showing how to extend the XML DOM classes (System.Xml), see www.gotdotnet.com/userfiles/XMLDom/extendDOM.zip.

The .NET Framework implementation of the DOM also includes an event system that enables you to receive and handle events when nodes in an XML document change. Using the XmlNodeChangedEventHandler and XmlNodeChangedEventArgs classes, you can capture NodeChanged, NodeChanging, NodeInserted, NodeInserting, NodeRemoved, and NodeRemoving events.

The event-handling process works exactly the same in derived classes as it would in the original DOM classes.

For more information regarding node event handling, see Handling and Raising Events and XmlNodeChangedEventHandler Delegate.

If you are overriding the CreateElement method in a derived class, default attributes are not added when you are creating new elements while editing the document. This is only an issue while editing. Because the CreateElement method is responsible for adding default attributes to an XmlDocument, you must code this functionality in the CreateElement method. If you are loading an XmlDocument that includes default attributes, they will be handled correctly. For more information on default attributes, see Creating New Attributes for Elements in the DOM.

Show:
© 2015 Microsoft