Figure 1

Figure 1 The System.Xml Namespace Architecture

Figure 1 The System.Xml Namespace Architecture
Figure 5 Console Output

  [XmlDeclaration]
[Whitespace] 
[Comment]
[Whitespace]
[ProcessingInstruction]
[Whitespace]
[Element]
[Whitespace] 
[Element] 
[Text]
[EndTag]  
[Whitespace] 
[Element] 
[Text]
[EndTag] 
[Whitespace] 
[EndTag]

Figure 6 Reading or Serializing Documents

  using System;
using System.Xml;

// rest of class omitted for clarity

public void ReadDocumentAndSerialize(XmlReader reader)
{
    // read each node in the tree
    while (reader.Read())
    {
        // serialize node out to console according to XML 1.0 + Names
    switch (reader.NodeType)
    {
      case XmlNodeType.Element:
        Console.Write("<" + reader.Name);
        while (reader.MoveToNextAttribute())
          Console.Write(" " + reader.Name + "='" + reader.Value + "'");
        Console.Write(">");
        break;
      case XmlNodeType.Text:
        Console.Write(reader.Value);
        break;
      case XmlNodeType.CDATA:
        Console.Write(reader.Value);
        break;
      case XmlNodeType.ProcessingInstruction:
        Console.Write("<?" + reader.Name + " " + reader.Value + "?>");
        break;
      case XmlNodeType.Comment:
        Console.Write("<!--" + reader.Value + "-->");
        break;
      case XmlNodeType.Document:
        Console.Write("<?xml version='1.0'?>");
        break;
      case XmlNodeType.Whitespace:
        Console.Write(reader.Value);
        break;
      case XmlNodeType.SignificantWhitespace:
        Console.Write(reader.Value);
        break;
      case XmlNodeType.EndTag:
        Console.Write("</" + reader.Name + ">");
        break;
    }
    }
}

Figure 7 XmlTextReader and Validation

  // if this works, it was written by Aaron Skonnard
// https://staff.develop.com/aarons

using System;
using System.Xml;

public class ValidateUtility
{
  static bool m_error = false;
  
  public static void Main(String[] args)
  {
    if (args.Length < 1)
    {
      Console.WriteLine("usage: validate filename [-dtd, 
          -schema, -none]");
      return;
    }
    try
    {
      // create instance of XmlTextReader
      XmlTextReader tr = new XmlTextReader(args[0]);

      // specify what type of validation to perform
      if (args.Length > 1)
      {
        if (args[1].Equals("-dtd"))
          tr.Validation = Validation.DTD;
        else if (args[1].Equals("-schema"))
          tr.Validation = Validation.Schema;
        else if (args[1].Equals("-none"))
          tr.Validation = Validation.None;
        else
          tr.Validation = Validation.Auto;
      }
      // register event callback (for validation errors)
       tr.ValidationEventHandler += new 
           ValidationEventHandler(ValidationCallback);

      // read through entire document
      while (tr.Read()) ;
      if (!m_error)
        Console.WriteLine("success: document is valid");
    }
    catch(XmlException e)
    {
      Console.WriteLine("###error: " + e.Message);
    }
    return;
  }

  public static void ValidationCallback (Object obj, 
      ValidationEventArgs args)
  {
     m_error = true;
     Console.Write("\r\n\t###validation error: " + args.Message);
  }
}

Figure 8 Configuring XmlTextReader

  using System;
using System.Xml;

public static void Main(String[] args)
{
  try
  {
    // file name passed in args[0]
    XmlTextReader tr = new XmlTextReader(args[0]);
    // specify custom entity resolver
    tr.XmlResolver = new MyResolver();
    // don't report whitespace
    tr.WhitespaceHandling = WhitespaceHandling.None;
    // optimize entity expansion
    // must call ResolveEntity to expand
    tr.EntityHandling = EntityHandling.AllEntityNodes;
    // use dtd/schema for entity expansion & default attributes
    // but don't validate
    tr.Validation = Validation.Auto;

    // read through the document      
    while (tr.Read())
    {
      // process nodes here
    }
  }
  catch(XmlException e)
  {
    Console.WriteLine("###error: " + e.Message);
  }
}

Figure 9 Custom XmlReader for Processing XIncludes

  // if this works, it was written by Aaron Skonnard
// https://staff.develop.com/aarons

using System;
using System.Xml;

public class XincUtility
{
  public static void Main(String[] args)
  {
    try
    {
      // create an instance of our custom XmlReader (XincReader) and 
      // configure
      XincReader r = new XincReader(args[0]);
      r.WhitespaceHandling = WhitespaceHandling.None;
      XmlTextWriter tw = new XmlTextWriter(Console.Out);
      tw.Formatting = Formatting.Indented;
      tw.WriteStartDocument();
      while (r.Read())
        SerializeNode(r, tw);
      tw.WriteEndDocument();
    }
    catch(XmlException e)
    {
      Console.WriteLine("###error: " + e.Message);
    }
    return;
  }

  public static void SerializeNode(XmlReader reader, XmlWriter w)
  {
    switch (reader.NodeType)
    {
      case XmlNodeType.Element:
        w.WriteStartElement(reader.Prefix, reader.LocalName, 
            reader.NamespaceURI);
        while (reader.MoveToNextAttribute())
        {
          w.WriteStartAttribute(reader.Prefix, reader.LocalName, 
              reader.NamespaceURI);
          w.WriteString(reader.Value);
          w.WriteEndAttribute();
        }
        break;
      case XmlNodeType.Text:
        w.WriteString(reader.Value);
        break;
      case XmlNodeType.CDATA:
        w.WriteCData(reader.Value);
        break;
      case XmlNodeType.ProcessingInstruction:
        w.WriteProcessingInstruction(reader.Name, reader.Value);
        break;
      case XmlNodeType.Comment:
        w.WriteComment(reader.Value);
        break;
      case XmlNodeType.EndTag:
        w.WriteEndElement();
        break;
    }
  }
}


public class XincReader : XmlTextReader
{
  // nested reader for processing XInclude elements
  XincReader m_NestedReader;
  
  public XincReader(String sURI) : base(sURI) {m_NestedReader=null;}

  // custom implementation of Read: if a nested reader exists, delegate
  // otherwise, Read the next node and check for xinc:href
  // if one exists create another nested reader and continue
  public override bool Read()
  {
    bool bMore;
    String strHref = null;

    // if nested reader exists, delegate
    if (m_NestedReader != null)
    {
      bMore = m_NestedReader.Read();
      // if done with nested reader, free resources & reset state
      if (!bMore)
      {
        m_NestedReader.Close();
        m_NestedReader = null;
        return base.Read();
      }
      else return true;
    }
    else
    {
      // read the next node and check for xinc:href
      bMore = base.Read();
      strHref = base.GetAttribute("href", 
          "https://www.w3.org/1999/XML/xinclude");
      // if found, create a new nested reader and move to the first node
      if (strHref != null)
      {
        m_NestedReader = new XincReader(strHref);
        m_NestedReader.Read();
        // move past XmlDeclaration if present
        if (m_NestedReader.NodeType == XmlNodeType.XmlDeclaration)
          m_NestedReader.Read();
        return true;
      }
      else
        return bMore;
    }
  }

  // override all of XmlTextReader's methods to delegate
  // to nested reader if one exists
  public string Name
  {
    override get
    {
      if (m_NestedReader != null)
        return m_NestedReader.Name;
      else
        return base.Name;
    }
  }

  public XmlNodeType NodeType
  {
    override get
    {
      if (m_NestedReader != null)
        return m_NestedReader.NodeType;
      else
        return base.NodeType;
    }
  }
  
  public string NamespaceURI
  {
    override get
    {
      if (m_NestedReader != null)
        return m_NestedReader.NamespaceURI;
      else
        return base.NamespaceURI;
    }
  }

  public string LocalName
  {
    override get
    {
      if (m_NestedReader != null)
        return m_NestedReader.LocalName;
      else
        return base.LocalName;
    }
  }

  public string Prefix
  {
    override get
    {
      if (m_NestedReader != null)
        return m_NestedReader.Prefix;
      else
        return base.Prefix;
    }
  }
  
  public string Value
  {
    override get
    {
      if (m_NestedReader != null)
        return m_NestedReader.Value;
      else
        return base.Value;
    }
  }

  public int AttributeCount
  {
    override get
    {
      if (m_NestedReader != null)
        return m_NestedReader.AttributeCount;
      else
        return base.AttributeCount;
    }
  }

  public override bool MoveToNextAttribute()
  {
    if (m_NestedReader != null)
      return m_NestedReader.MoveToNextAttribute();
    else
      return base.MoveToNextAttribute();
  }
  
  // others excluded for simplicity...
}

Figure 10 .NET DOM Class Hierarchy

Figure 10 .NET DOM Class Hierarchy
Figure 11 Generating a Document using the DOM

  using System;
using System.Xml;

public class GenerateDocument
{
  public static void Main(String[] args)
  {
    // instantiate the document
    XmlDocument doc = new XmlDocument();
    XmlNode node;

    // create a comment/pi and append
    node = doc.CreateComment("sample person document");
    doc.AppendChild(node);
    node = doc.CreateProcessingInstruction("hack", "on person");
    doc.AppendChild(node);

    // create the person element within the 'urn:person' namespace
    node = doc.CreateElement("p", "person", "urn:person");
    doc.AppendChild(node);
    // create the name/age elements in no namespace
    node = doc.CreateElement("name");
    node.InnerText = "joebob";
    doc.DocumentElement.AppendChild(node);
    node = doc.CreateElement("age");
    node.InnerText = "28";
    doc.DocumentElement.AppendChild(node);

    // serialize the document to the console
    XmlTextWriter tw = new XmlTextWriter(Console.Out);
    tw.Formatting = Formatting.Indented;
    doc.Save(tw);
  }
}

Figure 12 XPath Console Utility

  // if this works, it was written by Aaron Skonnard
// https://staff.develop.com/aarons

using System;
using System.Xml;

class XPathUtility
{
  public static void Main(String[] args)
  {
    if (args.Length < 2)
    {
      System.Console.WriteLine
          ("usage: xpath.exe filename xpath-expr [-eval]");
    }
    else
    {
      try
      {
        // load XML document w/input file
        XmlDocument doc = new XmlDocument();
        doc.Load(args[0]);
        // wrap with an XmlNavigaor
        DocumentNavigator nav = new DocumentNavigator(doc);

        // if -eval, call evaluate and return the result
        if (args.Length == 3 && args[2].Equals("-eval"))
        {
          Console.WriteLine(nav.Evaluate(args[1]));
          return;
        }
        // otherwise call Select
        nav.Select(args[1]);

        // create an XmlTextWriter to the console
        XmlTextWriter xw = new XmlTextWriter(Console.Out);
        xw.Formatting = Formatting.Indented;
        // create a new document for the selected nodes
        XmlDocument docoutput = new XmlDocument();
        XmlElement e = docoutput.CreateElement("selection");
        docoutput.AppendChild(e);
        DocumentNavigator navoutput = new DocumentNavigator(docoutput);
        navoutput.MoveToDocumentElement();
        // copy selected nodes to output document
        navoutput.CopySelected(TreePosition.FirstChild, nav);
        // serialize to console
        docoutput.Save(xw);
      }
      catch(Exception e)
      {
        System.Console.WriteLine("###error: " + e.Message);
      }
    }
  }
}

Figure 13 Transforming a Document with XslTransform

  // if this works, it was written by Aaron Skonnard
// https://staff.develop.com/aarons

using System;
using System.Xml;
using System.Xml.Xsl;

public class TransformationUtility
{
  public static void transformDocument(String strXML, 
      String strXSLT, XmlWriter xw)
  {
    try
    {
      // load the source document (to be transformed)
      XmlDocument docSource = new XmlDocument();
      docSource.Load(strXML);
      // wrap it with an XmlNavigator
      DocumentNavigator navSource = new DocumentNavigator(docSource);

      // create the XslTransform object
      XslTransform tr = new XslTransform();
      // load it with the stylesheet
      tr.Load(strXSLT);

      // call transform - output streamed to console
      tr.Transform(navSource, null, xw);
    }
    catch(XmlException e)
    {
      Console.WriteLine("###error: " + e.Message);
    }
  }

  public static void Main(String[] args)
  {
    if (args.Length < 2)
    {
      Console.WriteLine("usage: xslt sourcedoc xsltdoc [outdoc]");
      return;
    }
    if (args.Length == 3)
    {
      // create an XmlTextWriter to a file on disk
      XmlTextWriter tw = new XmlTextWriter(args[2], null);
      transformDocument(args[0], args[1], tw);
      return;
    }
    // otherwise send output to console
    transformDocument(args[0], args[1], new XmlTextWriter(Console.Out));
  }
}