Creating an XML File with VB 2010

Introduction

“If you want to improve, be content to be thought foolish and stupid.”

–Epictetus

I have been in the computer business long enough to remember removing physical disk platters–Winchester drive–from mini computers during data processing. I can remember pre-hard disks for PCs when a missing floppy caused a hard system crash and a solution was to hook the hard error interrupt 0x24 to contrive a sort of global exception handler. It seems like in those days one had to write every stitch of code by hand because the notion of frameworks was pretty foreign; we only had API’s and everything had to be handled at a pretty low level. It wasn’t uncommon to have assembly language modules as part of your build process.

Today a lot of the skills mentioned are probably only worth perspective. If you are a .NET developer then the .NET framework and to a lesser extent the Windows API is where you should be spending your time. Granted small things are a lot easier to do with a great framework. The only problem is there are more things to do in a given application than ever before.

For this article I elected to cover converting common data to an XML file and inferring the supporting XML Schema from that XML file. The solution relies heavily on LINQ to XML and functional composition. Functional composition means to use functions to create something. By working through this example you should learn some things about the structure of XML documents, XML schemas, and File IO.

Composing an XML Document from the File System

A clever application I used for a while was a wrapper for Visual Source Safe that let a user check in and check out files from a Web application. On the back end the Web application used SourceSafe’s Automation layer to read SourceSafe’s contents. The contents were converted into a file-like structure on a Web page and end user operations were sent back to the server, again using the Automation layer of SourceSafe to actually perform the operations and then deliver the content across the Web. The demo sort of simulates that; instead of SourceSafe the file system was used. The first part of the sample uses the Directory class in System.IO to enumerate all file system entries. The second part of the sample uses the file paths to create FileInfo objects and store these in a generic list. Taken from Listing 1 that code looks like this.


Dim files = Directory.EnumerateFileSystemEntries(“C:BooksEarthweb”, “*.*”,
 SearchOption.AllDirectories)

Dim infos As List(Of FileInfo) = New List(Of FileInfo)
infos.Clear()
Array.ForEach(files.ToArray(), Sub(f)
 Dim info As FileInfo = New FileInfo(f)
 If (info Is Nothing = False) Then infos.Add(info)
End Sub)


The first statement returns all files in all directories beginning with the directory defined in the first argument. Programmers used to have to write the recursive descent through the file system but not anymore. The second fragment uses Array.ForEach and a multline Lambda Sub-expression to store the FileInfo objects.

A Lambda expression is a condensed anonymous method. Basically, a Lambda expression is just a method with the extra syntactical elements removed-like qualifiers, method names, and argument types. Lambda expressions are commonly used where methods accept arguments of a generic delegate type like Func, Action, and Predicate. Here is Listing 1; it contains the directory reading statements and the LINQ to XML code.


Imports System.IO
Imports System.Xml.Linq
Imports System.Threading.Tasks
Imports System.Windows.Forms
Imports System.Xml.Schema
Imports System.Text
Imports System.Xml

Module Module1

   Sub Main()

     Dim files = Directory.EnumerateFileSystemEntries(“C:BooksEarthweb”, “*.*”,
       SearchOption.AllDirectories)

     Console.WriteLine(“=================================”)
     Console.WriteLine(“Found: {0}”, files.Count)
     Console.WriteLine(“=================================”)

     Dim infos As List(Of FileInfo) = New List(Of FileInfo)
     infos.Clear()
     Array.ForEach(files.ToArray(), Sub(f)
       Dim info As FileInfo = New FileInfo(f)
       If (info Is Nothing = False) Then infos.Add(info)
     End Sub)

     Dim doc As XDocument = New XDocument(
       New XDeclaration(“1.0”, “utf-8”, “true”),
       New XElement(“CodeGuru”,
         From info In infos
         Let ro = IIf(info.IsReadOnly, “+R”, “-R”)
         Select New XElement(“File”,
           New XAttribute(“Attributes”, info.Attributes),
           New XElement(“FileName”, info),
           New XElement(“CreationTime”, info.CreationTime),
           New XElement(“ReadOnly”, ro)
           )))

     ‘ save xml document with today’s date
     doc.Save(String.Format(“….{0}.xml”,
       DateTime.Now.ToShortDateString().Replace(“/”, “_”)))

     Console.ReadLine()

End Sub



Listing 1: Using File IO to read the file system and LINQ to XML to convert that data to an XML document.

Remember Functional Composition means to compose with function calls. The XDocument class is part of the System.Xml.Linq namespace. It represents an XML document. Write code like New XDocument(… is an example of Functional composition.

XDocument accepts a ParamArray of subordinate XML elements like XElement and XAttribute. The nested LINQ to XML statement begins with the From info in infos part of the compositor. The range variable–like an iterator variable in a for loop-is info. The source collection follows the in-clause. Lets define a temporary range variable that can be used for loops or in this case to add logic to the LINQ query. When you see “Select New” think projection. A projection can yield a new anonymous type or be used to construct an existing type as in this example.

The root element in the final document will be CodeGuru. The first child nodes will be File with the file’s attributes and the nested children FileName, CreationTime, and

ReadOnly

. An excerpt from the output of the code can be seen in Listing 2.


<?xml version=”1.0″ encoding=”utf-8″?>
<CodeGuru>
 <File Attributes=”Directory”>
   <FileName>C:BooksEarthwebGENERAL ARTICLES</FileName>
   <CreationTime>2009-04-19T16:10:22.355457-04:00</CreationTime>
   <ReadOnly>-R</ReadOnly>
 </File>
 <File Attributes=”Archive”>
   <FileName>C:BooksEarthwebSchedule_for_VB_Today.doc</FileName>
   <CreationTime>2009-04-19T16:10:22.355457-04:00</CreationTime>
   <ReadOnly>-R</ReadOnly>
 </File>
 <File Attributes=”Directory”>
   <FileName>C:BooksEarthwebSOURCE</FileName>
   <CreationTime>2009-04-19T16:10:22.6518589-04:00</CreationTime>
   <ReadOnly>-R</ReadOnly>
 </File>
 <File Attributes=”Directory”>
   <FileName>C:BooksEarthwebVideos</FileName>
   <CreationTime>2009-04-19T16:10:30.2959079-04:00</CreationTime>
   <ReadOnly>-R</ReadOnly>
 </File>



Listing 2: Part of the output from Listing 1 are some of the file contents from 11 years of writing the VB Today column. (There were 4000 elements on this particular PC.)

More by Author

Must Read