Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

C# XML Directory Lister

0.00/5 (No votes)
1 Oct 2001 1  
Generates a directory list as XML

This is an update to a project I wrote using the .NET alpha release. This version works with the .NET Beta 2 release.

I was looking for a useful little project to start learning C# and the .NET framework. In my job we do a lot of things with XML so I was interested in exercising some of the XML classes. In particular I wanted to see how XML and ADO+ fit together. The result is the code in this project.

This code generates a list of entries in a directory as XML. The XML can be returned to the caller as an XML string, a W3C DOM document, or an ADO+ DataSet.

A word of WARNING. To compile the attached code, you need to have the .NET Framework SDK Beta 2 installed which. You can get the .NET Framework SDK here. Please don't send me questions regarding installation of the SDK.

Below is the source code for the XML directory lister:

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

namespace GregHack.XMLStuff.Cs
{

   /// <summary>

   /// This class generates a list of files in a directory as XML.  It can

   /// return the XML as a string, a W3C DOM document, or a DataSet.  I

   /// wrote this code to learn about the XML capabilities of the framework

   /// work specifically with the DataSets.

   /// </summary>

   public class XMLDirectoryLister
   {
      private Boolean m_bUseDOMCalls;

      /// <summary>

      /// Constructor

      /// </summary>

      /// <param name="bUseDOMCalls">Use W3C DOM calls to build XML?</param>

      /// <returns>None</returns>

      public XMLDirectoryLister( Boolean bUseDOMCalls )
      {
         m_bUseDOMCalls = bUseDOMCalls;
      }
      
      /// <summary>

      /// This method generates a list of files in a directory as XML and

      /// returns the XML as a string.

      /// </summary>

      /// <param name="strDirectory">List files in this directory</param>

      /// <returns>A XML string with the directory file list</returns>

      public string
      getXMLString( string strDirectory )
      {
         string strXML = "";
      
         XmlDocument doc = getXML( strDirectory );
         if ( doc != null )
         {
		      StringWriter writer = new StringWriter();
            doc.Save( writer );
            strXML = writer.ToString();
         }

         doc = null;
         return strXML;
      }
       

      /// <summary>

      /// This method generates a list of files in a directory as XML and

      /// returns the XML as a DataSet.

      /// </summary>

      /// <param name="strDirectory">List files in this directory</param>

      /// <returns>A DataSet with the directory file list</returns>

      public DataSet
      getXMLDataset( string strDirectory )
      {
         DataSet ds = null;
      
         string strXML = getXMLString( strDirectory );
         XmlDataDocument datadoc = new XmlDataDocument();
         datadoc.DataSet.ReadXml( new StringReader(strXML) );

         ds =  datadoc.DataSet;    
          
         return ds;
      }
       

      /// <summary>

      /// This public method generates a list of files in a directory as XML and

      /// returns the XML as a W3C DOM document.

      /// </summary>

      /// <param name="strDirectory">List files in this directory</param>

      /// <returns>A W3C DOM docuemnt with the directory file list</returns>

      public XmlDocument
      getXMLDocument( string strDirectory )
      {
         return getXML( strDirectory );
      }
   
      private XmlDocument
      getXML( string strDirectory )
      {
         XmlDocument xmlDoc;
         if ( m_bUseDOMCalls )
            xmlDoc = getXMLUsingDOMCalls( strDirectory );
         else
            xmlDoc = getXMLUsingTextWriterClass( strDirectory );
         
         return xmlDoc;
      }

      /// <summary>

      /// This private method generates a list of files in a directory as XML and

      /// returns the XML as a W3C DOM document using the DOM calls.

      /// </summary>

      /// <param name="strDirectory">List files in this directory</param>

      /// <returns>A W3C DOM docuemnt with the directory file list</returns>

      private XmlDocument
      getXMLUsingDOMCalls( string strDirectory )
      {
         // Create the document.

         XmlDocument doc = new XmlDocument();

         // Insert the xml processing instruction and the root node

         XmlDeclaration dec = 
            doc.CreateXmlDeclaration("1.0", "", "yes");
         doc.PrependChild ( dec );

         // Add the root element

         XmlElement nodeElem = 
            doc.CreateElement( "dirlist" );
         doc.AppendChild( nodeElem );
         
         Boolean bFirst = true;

         // Process the directory list

         DirectoryInfo dir = new DirectoryInfo( strDirectory );
         foreach ( FileSystemInfo entry in dir.GetFileSystemInfos() ) 
         {
            if ( bFirst == true )
            {
               // If we haven't added any elements yet, go ahead and add a text element which

               // contains the full directory path.

               XmlElement root = doc.DocumentElement;

               String strFullName = entry.FullName;
               String strFileName = entry.Name;
         
               String strDir = strFullName.Substring( 0, strFullName.Length - strFileName.Length );
               root.SetAttribute ("dir", strDir );

               bFirst = false;
            }   
            
            // Add a new text node with a tag entry.  There will be one added per

            // item encountered in the directory.

            XmlElement elem = doc.CreateElement("entry");
            doc.DocumentElement.AppendChild(elem);
            
            // Write out the things we are interested in about this entry in the

            // directory.

            addTextElement( doc, elem, "name", entry.Name );
            addTextElement( doc, elem, "created", entry.CreationTime.ToString() );
            addTextElement( doc, elem, "lastaccess", entry.LastAccessTime.ToString() );
            addTextElement( doc, elem, "lastwrite", entry.LastWriteTime.ToString() );
            addTextElement( doc, elem, "isfile", ( (entry.Attributes & FileAttributes.Directory) > 0 ) ? "False" : "True" );
            addTextElement( doc, elem, "isdir", ( (entry.Attributes & FileAttributes.Directory) > 0 ) ? "True" : "False" );
            addTextElement( doc, elem, "readonly", ( (entry.Attributes & FileAttributes.ReadOnly) > 0 ) ? "True" : "False" );
         }
               
         return doc;
      } 
       

      /// <summary>

      /// This private method adds a text element to the XML document as the last

      /// child of the current element.

      /// </summary>

      /// <param name="doc">The XML document</param>

      /// <param name="nodeParent">Parent of the node we are adding</param>

      /// <param name="strTag">The tag of the element to add</param>

      /// <param name="strValue">The text value of the new element</param>

      private void
      addTextElement( XmlDocument doc, XmlElement nodeParent, string strTag, string strValue )
      {
          XmlElement nodeElem = doc.CreateElement( strTag );
          XmlText nodeText = doc.CreateTextNode( strValue );
          nodeParent.AppendChild( nodeElem );
          nodeElem.AppendChild( nodeText );
      } 


      /// <summary>

      /// This private method generates a list of files in a directory as XML and

      /// returns the XML as a W3C DOM document using the XmlTextWriter class.

      /// </summary>

      /// <param name="strDirectory">List files in this directory</param>

      /// <returns>A W3C DOM docuemnt with the directory file list</returns>

      private XmlDocument
      getXMLUsingTextWriterClass( string strDirectory )
      {
         StringWriter writerString = new StringWriter();
        
         XmlTextWriter writer = new XmlTextWriter( writerString );
         
         writer.WriteStartDocument(true);
         
         Boolean bFirst = true;
      
         // Process the directory list

         DirectoryInfo dir = new DirectoryInfo( strDirectory );
         foreach ( FileSystemInfo entry in dir.GetFileSystemInfos() ) 
         {
            
            if ( bFirst == true )
            {
               // If we haven't added any elements yet, go ahead and add a text element which

               // contains the full directory path.

               writer.WriteStartElement( "dirlist", "" );

               String strFullName = entry.FullName;
               String strFileName = entry.Name;
               String strDir = strFullName.Substring( 0, strFullName.Length - strFileName.Length );

               writer.WriteAttributeString( "dir", strDir );
               bFirst = false;
            }   

            // Add a new text node with a tag entry.  There will be one added per

            // item encountered in the directory.

            writer.WriteStartElement( "entry", "" );
         
            // Write out the things we are interested in about this entry in the

            // directory.

            writer.WriteElementString( "name", entry.Name );
            writer.WriteElementString( "created", entry.CreationTime.ToString() );
            writer.WriteElementString( "lastaccess", entry.LastAccessTime.ToString() );
            writer.WriteElementString( "lastwrite", entry.LastWriteTime.ToString() );
            writer.WriteElementString( "isfile", ( (entry.Attributes & FileAttributes.Directory) > 0 ) ? "False" : "True" );
            writer.WriteElementString( "isdir", ( (entry.Attributes & FileAttributes.Directory) > 0 ) ? "True" : "False" );
            writer.WriteElementString( "readonly", ( (entry.Attributes & FileAttributes.ReadOnly) > 0 ) ? "True" : "False" );
   
            writer.WriteEndElement();    // entry     

         }

         writer.WriteEndElement();       // dirlist

         writer.WriteEndDocument();

         string strXML = writerString.ToString();
         StringReader reader = new StringReader( strXML );
               
         XmlDocument doc = new XmlDocument();
         doc.Load( reader );
         
         return doc;
      } 
   }
}

The first thing of interest is the following code:

namespace GregHack.XMLStuff.Cs

This says that I am creating a namespace for my code. Code that references the XMLDirectoryLister will have to include the following line:

using GregHack.XMLStuff.Cs;

The meat of the work is done in the getXMLUsingDOMCalls() and the getXMLUsingTextWriterClass() methods. They both create a W3C document via the XmlDocument class of the .NET framework but using alternate methods to do so. The first method uses the XmlDocument class of the framework to add to and traverse the XML document. The second method uses the XMLTextWriter class to accomplish the same thing.

Both implementations loop through all of the entries in the directory using the foreach syntax of C#:

foreach ( FileSystemEntry entry in dir.GetFileSystemEntries() )

The XmlDocument version uses the AppendChild() method to insert elements into the document that represent the entries in the directory. The XMLTextWriter version uses WriteElementString() to accomplish the same thing.

Something that I thought was pretty cool is how easy it is to translate XML into an ADO+ DataSet. The following lines of code that are in the getXMLDataset are all that are needed:

DataSet ds = null;
string strXML = getXMLString( strDirectory );
XmlDataDocument datadoc = new XmlDataDocument();
datadoc.DataSet.ReadXml( new StringReader(strXML) );
ds = datadoc.DataSet;    
return ds;

The ReadXml method will parse the XML passed in and come up with a database schema based on the XML.

The sample project contains a command line test .exe and a the XMLDirectoryLister compiled as a DLL. It generates XML of the form:

<?xml version='1.0' ?>
<dirlist dir="C:\anet\XML Directory\">
  <entry>
    <name>XMLDirectoryLister.bak</name>
    <created>9/21/2000 21:13:34</created>
    <lastaccess>9/21/2000 00:00:00</lastaccess>
    <lastwrite>9/21/2000 21:53:54</lastwrite>
    <isfile>True</isfile>
    <isdir>False</isdir>
    <readonly>False</readonly>
  </entry>
  <entry>
    <name>XMLDirectoryLister.dll</name>
    <created>9/21/2000 19:19:13</created>
    <lastaccess>9/21/2000 00:00:00</lastaccess>
    <lastwrite>9/21/2000 21:12:20</lastwrite>
    <isfile>True</isfile>
    <isdir>False</isdir>
    <readonly>False</readonly>
  </entry>
</dirlist>

When the getXMLDataset() method is called, it returns a DataSet with two tables dirlist and entry. Entry has 7 columns, name, created, lastaccess, lastwrite, isfile, isdir, readonly. You can see the relationship between the XML and the tables.

One last thing of interest is the class and method documentation. You'll notice it uses three forward slashes and some XML tags. If you use this style you can tell the compiler to emit XML documentation as output. It will then create and XML file containing the documentation you put in your source file. The XML could then be rendered as HTML or some other format to document you source. Use a specifier in your makefile such as /doc:XMLDirectoryLister.xml to emit the XML documentation file. The sample project contains the XML documentation emitted by the compiler.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here