Figures
© 2004 Microsoft Corporation. All rights reserved.
Figure 6 Custom XPathNavigator Template
public class MyNavigator : XPathNavigator
{
  // abstract properties to override
  public override string LocalName { get {} }
  public override string NamespaceURI { get{} }
  public override string Name { get{} }
  public override string Prefix { get{} }
  public override XPathNodeType NodeType { get{} }
  public override string Value { get{} }
  public override string BaseURI { get{} }
  public override string XmlLang { get{} }
  public override bool IsEmptyElement { get{} }
  public override XmlNameTable NameTable { get{} }
  public override bool HasAttributes { get{} }
  public override bool HasChildren { get{} }

  // abstract methods to override

  // methods for moving through the tree
  public override bool MoveToNext() {}
  public override bool MoveToPrevious() {}
  public override bool MoveToFirst() {}
  public override bool MoveToFirstChild() {}
  public override bool MoveToParent() {}
  public override void MoveToRoot() {}
  public override bool MoveTo(XPathNavigator other) {}
  public override bool MoveToId(string id) {}
  public override bool IsSamePosition(
    XPathNavigator other) {}
  public override XPathNavigator Clone() {}

  // methods for accessing attribute nodes
  public override string GetAttribute(
    string localName, string namespaceURI) {}
  public override bool MoveToAttribute( 
    string localName, string namespaceURI) {}
  public override bool MoveToFirstAttribute() {}
  public override bool MoveToNextAttribute() {}

  // methods for accessing namespace nodes
  public override string GetNamespace(string prefix) {}
  public override bool MoveToNamespace(string prefix) {}
  public override bool MoveToFirstNamespace() {}
  public override bool MoveToNextNamespace() {}
}
Figure 8 ZIP File as XML
<contents>
  <fsnav_x005C_bin path="fsnav\bin\" 
    compressedSize="0" uncompressedSize="0" 
    lastModified="05/30/01 14:22:40" />
  <aaronsziputilslib.dll 
    path="fsnav\bin\AARONSZIPUTILSLib.dll" 
    compressedSize="1492" uncompressedSize="4096" 
    lastModified="05/30/01 14:22:34" />
  <developmentor.xml.dll 
    path="fsnav\bin\Developmentor.Xml.dll" 
    compressedSize="18595" uncompressedSize="57344" 
    lastModified="05/30/01 14:22:38" />
  <fsnav.exe path="fsnav\bin\fsnav.exe" 
    compressedSize="2749" uncompressedSize="8704" 
    lastModified="05/30/01 14:22:40" />
  <fsnav.pdb path="fsnav\bin\fsnav.pdb" 
    compressedSize="1461" uncompressedSize="13824" 
    lastModified="05/30/01 14:22:40" />
  <fsnav.cs path="fsnav\fsnav.cs" 
    compressedSize="1362" uncompressedSize="5284" 
    lastModified="05/23/01 14:18:40" />
  <makefile path="fsnav\makefile" 
    compressedSize="417" uncompressedSize="929" 
    lastModified="05/23/01 14:37:32" />
  <fsnav path="fsnav\" 
    compressedSize="0" uncompressedSize="0" 
    lastModified="05/30/01 14:22:38" />
</contents>
Figure 9 State Machine for ZipNavigator
namespace Developmentor.Xml
{
  using System;
  using System.IO;
  using System.Xml;    
  using System.Xml.XPath;
  using System.Collections;
  using AARONSZIPUTILSLib;

  internal class ZipState
  {
    public Object currentObject;
    public ZipState parent;
    public int indexOfCurrentInParent;
    public int indexOfAttribute;
    public ZipNavigator owner;
    // for other types of nodes: #document, #text
    public string nonEntryName; 
    // attribute names
    public static string[] atts = 
    { 
      "path", 
      "compressedSize", 
      "uncompressedSize" 
    };

    internal ZipState()
    {
      this.indexOfCurrentInParent = -1;
      this.indexOfAttribute = -1;
      this.nonEntryName = "";
    }

    internal ZipState(Object current, ZipState p, 
      int index, string neName, ZipNavigator nav)
    {
      this.currentObject = current;
      this.parent = p;    
      this.nonEntryName = neName;
      this.indexOfCurrentInParent = index;
      this.indexOfAttribute = -1;
      this.owner = nav;
    }

    public ZipState Clone()
    {
      ZipState astate = new ZipState();
      astate.currentObject = this.currentObject;
      astate.nonEntryName = this.nonEntryName;
      astate.parent = this.parent;
      astate.indexOfCurrentInParent = 
        this.indexOfCurrentInParent;
      astate.indexOfAttribute = this.indexOfAttribute;
      astate.owner = this.owner;
      return astate;
    }

    public ZipState OpenChild(int childIndex)
    {
      ZipState ast = null;

      if (IsDocument)
      {
        if (childIndex > 0)
          return null;
        ast = new ZipState(owner.zip, this, 0, 
          "contents", owner);
      }
      else if (IsAttribute)
      {
        if (childIndex > 0)
          return null;
        ast = 
          new ZipState(null, this, 0, "#text", owner);
      }
      else if (childIndex >= 0 && childIndex<ChildCount)
        ast = 
          new ZipState(null, this, childIndex,"",owner);
      else return null;
      return ast;
    }            

    public string Name 
    { 
      get 
      { 
        if (IsAttribute)
          return AttributeNames[indexOfAttribute];
        else if (IsZipItem)
        {
          string name = 
            ((AARONSZIPUTILSLib.ZipReader)
               owner.zip).GetFileName(
                 indexOfCurrentInParent).ToLower();
          int index = name.LastIndexOf("\\");
          if (index >= 0)
          {
            string encName = 
              XmlConvert.EncodeLocalName(
                name.Substring(index+1));
            if (encName.Length == 0)
              return XmlConvert.EncodeLocalName(
                name.Substring(0, index));
            else
              return encName;
          }
          else
            return XmlConvert.EncodeLocalName(name);
        }
        else
          return nonEntryName;
      }
    }

    public int ChildCount 
    { 
      get 
      {
        if (IsDocument)
          return 1;
        else if (IsDocumentElement)
          return ((AARONSZIPUTILSLib.ZipReader)
            owner.zip).GetCount();
        else if (IsAttribute)
          return 1; 
        else if (IsTextNode)
          return 0;
        else
          return 0;
      }
    }

    public string GetAttribute(string name) 
    {
      if (IsZipItem)
      {
        AARONSZIPUTILSLib.ZipReader myzip = 
          (AARONSZIPUTILSLib.ZipReader)owner.zip;
        switch(name)
        {
        case "path":
          return myzip.GetFileName(
            indexOfCurrentInParent);
        case "compressedSize":
          return myzip.GetCompressedSize(
            indexOfCurrentInParent).ToString();
        case "uncompressedSize":
          return myzip.GetUncompressedSize(
            indexOfCurrentInParent).ToString();
        default:
          break;
        }
      }
      return "";
    }        

    ...    // rest of class omitted for clarity
}
Figure 10 ZipNavigator Class
namespace Developmentor.Xml
{
  using System;
  using System.IO;
  using System.Xml;    
  using System.Xml.XPath;
  using System.Collections;
  using AARONSZIPUTILSLib;

  public class ZipNavigator : XPathNavigator
  {
    private ZipState state;
    private string zipFileName;
    private XmlNameTable nt = new NameTable();
    public AARONSZIPUTILSLib.ZipReader zip;

    public ZipNavigator(string zipFileName)
    {
      this.zip = new AARONSZIPUTILSLib.ZipReader();
      this.zipFileName = zipFileName;
      this.state = 
        new ZipState(null, null, -1, "#document", this);
      zip.Open(zipFileName);
    }

    private ZipNavigator(ZipState s, 
      AARONSZIPUTILSLib.ZipReader zr)
    {
      this.zip = zr;
      this.state = s;
    }

    public override XPathNavigator Clone()
    {
      return 
        new ZipNavigator(this.state.Clone(), this.zip);
    }
        
    public override XPathNodeType NodeType
    { 
      get 
      {
        if (state.IsDocument)
          return XPathNodeType.Root;
        else if (state.IsAttribute)
          return XPathNodeType.Attribute;
        else if (state.IsTextNode)
          return XPathNodeType.Text;
        else 
          return XPathNodeType.Element;
      }
    }   
    public override string LocalName 
    { 
      get { return nt.Add(state.Name); }
    }
    public override string NamespaceURI 
    { 
      get { return nt.Add(string.Empty); } 
    }
    public override string Name 
    { 
      get { return nt.Add(state.Name); }
    }
    public override string Prefix 
    { 
      get { return nt.Add(string.Empty); }
    }
    public override bool IsEmptyElement
    { 
      get
      { 
        if (state.IsAttribute || state.IsTextNode)
          return false;
        return !HasChildren;
      }
    }
    public override bool HasAttributes
    {
      get { return AttributeCount > 0; }
    }
    public override bool HasChildren 
    { 
      get { return (state.ChildCount > 0); }
    }

    public override string GetAttribute(
      string localName, string namespaceURI )
    {
      if (namespaceURI.Equals(""))
        return state.GetAttribute(localName);
      else
        return "";
    }
                      
    private bool UpdateState(ZipState s)
    {
      if (s == null)
        return false;
      else
      {
        state = s;
        return true;
      }
    }

    public override bool MoveToNext()
    {
      if (state.IsAttribute)
        return false;
      ZipState p = state.parent;
      if (p!=null && (IndexInParent+1 < p.ChildCount))
      {
        ZipState newState = p.OpenChild(IndexInParent+1);
        return UpdateState(newState);
      }
      return false;
    }
        
    public override bool MoveToPrevious()
    {
      if (state.IsAttribute)
        return false;
      ZipState p = state.parent;
      if (p!=null && (IndexInParent-1 >= 0))
      {
        ZipState newState = p.OpenChild(IndexInParent-1);
        return UpdateState(newState);
      }
      return false;
    }
   
    public override bool MoveToFirstChild()
    {
      ZipState newState = state.OpenChild(0);
      return UpdateState(newState);
    }
        
    public override bool MoveToParent()
    {
      if (state.IsAttribute)
      {
        state.indexOfAttribute = -1;
        return true;
      }
      if (state.parent != null)
      {
        state = state.parent;
        return true;
      }
      return false;
    }

    public override void MoveToRoot()
    {
      state = new ZipState(null, null, -1, "#document",
        this);
    }

    public override bool MoveTo(XPathNavigator other)
    {
      if (other is ZipNavigator)
      {
        ZipNavigator asn = (ZipNavigator)other;
        state = asn.state.Clone();
        return true;
      }
      return false;
    }

    // ... rest of class omitted for clarity
  }
}
Figure 12 Assembly File as XML
<person isa="assembly" codebase="file:///C:/Temp/person.dll"
   location="c:/temp/person.dll">
  <person.dll isa="module" qname="c:\temp\person.dll" 
    scopename="person.dll">
    <Person isa="type" qname="Example.Person" 
      typetype="class" abstract="False" visibility="public" 
      sealed="False" serializable="False" basetype="Object" 
      underlying="Person" 
      guid="2e3aa5c8-7104-3a9a-ba6f-6aa433101d35">
      <ctor isa="constructor" abstract="False" 
        visibility="public" final="False" static="False" 
        virtual="False" callconv="Standard, HasThis" />
      <name isa="field" type="String" visibility="public" 
        literal="False" initonly="False" 
        notserialized="False" static="False" />
      <age isa="field" type="Double" visibility="public" 
        literal="False" initonly="False" 
        notserialized="False" static="False" />
      <GetHashCode isa="method" rettype="Int32" 
        abstract="False" visibility="public" final="False" 
        static="False" virtual="True" 
        callconv="Standard, HasThis" />
      <Equals isa="method" rettype="Boolean" 
        abstract="False" visibility="public" final="False" 
        static="False" virtual="True" 
        callconv="Standard, HasThis">
        <obj isa="parameter" type="Object" default="" 
          optional="False" in="False" out="False" 
          retval="False" />
      </Equals>
      <ToString isa="method" rettype="String" 
        abstract="False" visibility="public" final="False"
        static="False" virtual="True" 
        callconv="Standard, HasThis" />
      <GetType isa="method" rettype="Type" abstract="False" 
        visibility="public" final="False" static="False" 
        virtual="False" callconv="Standard, HasThis" />
    </Person>
  </person.dll>
</person>
Figure 13 File System as XML
<mycomputer>
  <c type="dir" creationTime="5/14/2001 6:45:29 PM" 
    lastAccessTime="5/30/2001 3:28:59 PM" 
    lastWriteTime="5/23/2001 3:03:52 PM" fullName="C:\">
    <data type="dir" creationTime="5/15/2001 9:24:54 PM" 
      lastAccessTime="5/30/2001 3:33:16 PM" 
      lastWriteTime="5/30/2001 3:33:02 PM" 
      fullName="C:\data">
      <sync.bat type="file" 
        creationTime="5/19/2001 12:22:44 PM" 
        lastAccessTime="5/19/2001 12:22:44 PM" 
        lastWriteTime="9/10/2000 11:08:25 AM" 
        fullName="C:\data\sync.bat" length="19" />
      <!-- other child directories and files go here -->
      ...
    </data>
    <!-- other child directories and files go here -->
    ...
  </c>
  <!-- other logical drives go here -->
</mycomputer>
Figure 14 Traversing a Navigator
public static void SerializeNode(XmlWriter w, 
  XPathNavigator nav)
{
  switch (nav.NodeType)
  {
  case XPathNodeType.Element:
    w.WriteStartElement(nav.Prefix, nav.LocalName, 
      nav.NamespaceURI);
    if (nav.MoveToFirstAttribute())
    {
      w.WriteStartAttribute(nav.Prefix, nav.LocalName, 
        nav.NamespaceURI);
      w.WriteString(nav.Value);
      w.WriteEndAttribute();
      while (nav.MoveToNextAttribute())
      {
        w.WriteStartAttribute(nav.Prefix, nav.LocalName, 
          nav.NamespaceURI);
        w.WriteString(nav.Value);
        w.WriteEndAttribute();
      }
      nav.MoveToParent();
    }
    if (nav.HasChildren)
    {
      bool more = nav.MoveToFirstChild();
      while (more)
      {
        SerializeNode(w, nav, descendants, attributes);
        more = nav.MoveToNext();
      }
      nav.MoveToParent();
    }
    w.WriteEndElement();
    break;
  case XPathNodeType.Text:
    w.WriteString(nav.Value);
    break;
  case XPathNodeType.ProcessingInstruction:
    w.WriteProcessingInstruction(nav.Name, nav.Value);
    break;
  case XPathNodeType.Comment:
    w.WriteComment(nav.Value);
    break;
  case XPathNodeType.Whitespace:
  case XPathNodeType.SignificantWhitespace:
    // ignore whitespace
    break;
  }            
}
Figure 15 Using Custom Navigators
public void TraverseAndSerializeNavigators()
{
  // traverse an XML document
  XmlDocument doc = new XmlDocument();
  doc.Load("foo.xml");
  XPathNavigator xn = 
    ((IXPathNavigable)doc).CreateNavigator();
  SerializeNode(new XmlTextWriter(Console.Out), xn);

  // traverse a zip file as XML
  ZipNavigator zn = new ZipNavigator("fsnav.zip");
  SerializeNode(new XmlTextWriter(Console.Out), zn);

  // traverse a .NET assembly as XML
  AssemblyNavigator an = new 
    AssemblyNavigator("person.dll");
  SerializeNode(new XmlTextWriter(Console.Out), an);

  // traverse the file system as XML
  FileSystemNavigator fsn = new FileSystemNavigator();
  SerializeNode(new XmlTextWriter(Console.Out), fsn);

  // traverse the Windows registry as XML
  RegistryNavigator rn = new RegistryNavigator();
  SerializeNode(new XmlTextWriter(Console.Out), rn);
}
Figure 17 Registering File Handlers
public FileSystemNavigator CreateAndInitialize()
{
  FileSystemNavigator nav = new FileSystemNavigator();
  // register the default handler for XML files
  nav.RegisterFileHandler(".xml", 
    "Developmentor.Xml.XmlDocumentNavigatorFactory", 
    "Developmentor.Xml");
  // register the default handler for zip files
  nav.RegisterFileHandler(".zip", 
    "Developmentor.Xml.ZipNavigatorFactory", 
    "Developmentor.Xml");
  // register the default handler for assembly files 
  nav.RegisterFileHandler(".dll", 
    "Developmentor.Xml.AssemblyNavigatorFactory", 
    "Developmentor.Xml");
  return nav;
}
Figure 19 Custom XmlReader Template
public class MyReader : XmlReader 
{
  // same as XPathNavigator
  // properties
  public override string LocalName { get{} }
  public override string NamespaceURI { get{} }
  public override string Name { get{} }
  public override string Prefix { get{} } 
  public override XmlNodeType NodeType { get{} }
  public override string Value { get{} }
  public override string BaseURI { get{} }
  public override string XmlLang { get{} }
  public override bool IsEmptyElement { get{} } 
  public override XmlNameTable NameTable { get{} }
  public override bool HasAttributes { get{} }
  // methods
  public override string GetAttribute(string name, 
    string namespaceURI) {}
  public override bool MoveToFirstAttribute() {}
  public override bool MoveToNextAttribute() {}
  public override bool MoveToAttribute(string name, 
    string ns) {}

  // specific to XmlReader
  // properties
  public override int AttributeCount { get{} }
  public override string this[int index] { get{} }
  public override string this[string name] { get{} }
  public override string this[string localName, 
    string nsURI] { get{} }
  public override int Depth { get{} }
  public override bool HasValue { get{} }
  public override bool IsDefault { get{} }
  public override bool EOF { get{} }
  public override ReadState ReadState { get{} } 
  public override Char QuoteChar { get{} }
  public override XmlSpace XmlSpace { get{} }
  // methods
  public override string GetAttribute(int i) {}
  public override string GetAttribute(string name) {}
  public override void MoveToAttribute(int index) {}
  public override bool MoveToAttribute(string name) {}
  public override bool ReadAttributeValue() {}
  public override bool MoveToElement() {}
  public override string LookupNamespace(string prefix){}
  public override bool Read() {}
  public override string ReadInnerXml() {}
  public override string ReadOuterXml() {}
  public override string ReadString() {}
  public override void ResolveEntity() {}
  public override void Close() {}
}
Page view tracker