This tutorial walks through a sample application that Microsoft provides where an XML file is loaded into memory and then can be queried using a console application written in VB.NET. Not only does this help us as we learn to write Visual Basic applications, it also allows us to see a simple example of what XML looks like, how it can be used like a database, and how the DotNet runtime can interact with it. We also get a demonstration of how to output data to the console, input data from the user, use if conditions, and while loops. Not bad for a little app that’s under 100 lines of code.
This tutorial is broken up into two parts. The first part is meant for beginners who want to learn how a console application works and how to use some basic Visual Basic commands such as the If, Then statement and While loops. If you are already familiar with this you can skip to part 2. Part 2 focuses on how to define an XML file, how to read it in to a DataSet, and how to query it using a DataView.
Note: This tutorial walks through a sample application. It is recommended that you download and open it as you go through this tutorial:
To create a console application all we need to do is define a subroutine named main with no parameters:
Module MainModule Sub Main() End Sub End Module
If you run the application after doing this it will open a command prompt, do nothing, and then close. All and all not very exciting. However, once we add code between the Sub Main() and End Sub things will start getting much more interesting, as you can see in the example this tutorial uses.
One of the things you will notice right away when you run the sample application is that it displays a message to the console that says welcome and gives instructions on what to do. These messages are displayed using VB.NET’s Console.WriteLine() function.
Console.WriteLine(welcomeMessage) ... Console.WriteLine() Console.WriteLine(promptMessage)
The write line function does exactly what it says. It writes out the string specified and then also writes out a new line character. This has the effect of causing the next statement to be written to the console to be on the next line. Another Console function is simply Write(). This function will write the string to the console and then leave the cursor at the end of the string.
Reading data from the console is also very easy to do with the Console.ReadLine() function. This function reads what ever the user types in (until they hit the enter key). Then it returns this value as a string that we can assign to a variable. In our source code you will see this (around line 36).
Console.WriteLine("A numeric product ID is required.") Console.WriteLine("Please reenter the Product ID or QUIT to continue.") strInput = Console.ReadLine()
So in the code above we first write out a couple of lines to explain to the user what they need to enter. We then wait for them to enter something and press enter. The string that they enter will be stored in the strInput variable for us to use.
Visual Basic like most programming languages provides an if condition command. This command allows us to easily perform code based on the specified condition. Basically anything after the Then and before the End If statements is executed only if the condition portion is met. For example lets look at our sample VB code again (around line 39).
' Exit on "quit". If UCase(strInput) = "QUIT" Then End End If
This code is the equivalent of saying the following sentence in English: If the upper case value of the string input by the user is “QUIT” then end our application, if it is not then skip over this and continue on.
Side Note: This is one area where I disagree with the Microsoft example. Instead of using the UCase command we can simply use strInput.Equals(…) command with the ignore case flag, but either way works fine.
Another VB construct you will notice in this code is the use of a couple of while loops. While loops are similar to if statements in that they execute based on the condition specified. The difference is that the code is executed over and over again while the condition is true (instead of just once like in an if statement). Lets examine one of these from our source (around line 33):
While Not (IsNumeric(strInput) Or UCase(strInput) = "QUIT") Console.WriteLine("A numeric product ID is required.") Console.WriteLine("Please reenter the Product ID or QUIT to continue.") strInput = Console.ReadLine() End While
This is equivalent to saying while the input string is not a number and is not “quit” write out a prompt and get the input string again. This means that if you run the application and enter “blah”, it will simply ignore what you entered, re-ask you to enter a product ID or QUIT, and wait. This will keep happening until you enter a number or the string quit.
If you look above this loop in our code (around line 30) you will see another while loop:
While strInput <> "QUIT"
This while loop is much larger than our other one. You will find the end of it almost at the end of our source file (around line 72). This loop makes it so that after the user sees the data for a certain product the entire process starts over and they are asked to enter a product ID again. This will keep happening until the user types “QUIT”.
XML (eXtensible Markup Language) is a standard that has been around for some time now. It came about as an easy way to define data a standard format that is both easy for a computer to process and fairly easy for a human to read and understand. Lets take a look at a chunk of XML that our sample application uses:
<DataSet1 xmlns="http://www.tempuri.org/DataSet1.xsd"> <Products> <ProductID>1</ProductID> <ProductName>Chai</ProductName> <SupplierID>1</SupplierID> <CategoryID>1</CategoryID> <QuantityPerUnit>10 boxes x 20 bags</QuantityPerUnit> <UnitPrice>18.0000</UnitPrice> <UnitsInStock>39</UnitsInStock> <UnitsOnOrder>0</UnitsOnOrder> <ReorderLevel>10</ReorderLevel> <Discontinued>false</Discontinued> </Products> <Products> ...
Easy to read right? Well if not I will summarize what we are defining here. Basically the outer tag is saying that what we have is a DataSet. Microsoft’s DataSet class will be able to parse this because of this tag. Then the Products tag says that this is defining one product (out of many). In fact if you look at the Products.XML file that ships in this sample you will see that we have many many products defined. Every tag under the Products one Identifies a field in the product and its value. For example the ProductID field has a value of 1. The ProductName field has a value of Chai. So on and so forth. This is an easy way for us to put some sample data in our application with out having to worry about shipping a whole database or parsing a binary file.
In our sample the method that gets called to read this XML into a VB.NET DataSet is called CreateDataSet the code for it is at the end of the source file (around line 80) and the variables that it works with are at the top of the file (around line 8). Here is the relevant code:
Private dsProducts As New DataSet Private dvProducts As DataView ... Private Sub CreateDataSet() Dim thisExe As System.Reflection.Assembly thisExe = System.Reflection.Assembly.GetExecutingAssembly() Dim xmlFile As System.IO.Stream xmlFile = thisExe.GetManifestResourceStream("ConsoleApp.Products.xml") dsProducts.ReadXml(xmlFile) dvProducts = New DataView(dsProducts.Tables(0)) dvProducts.Sort = "ProductID" End Sub
Not too much code so lets take it line by line. The first to lines just declare our DataSet variable and our DataView variable. We will use these to load the XML file and query it. Now moving into our CreateDataSet subroutine. The first two lines grab our current executing program assembly. The next two lines load our xmlFile from the resource area of our program. If you don’t understand these lines of code exactly don’t worry about it. What we end up with at this point is a variable xmlFile that is basically all the xml in the Products.xml file.
Now we tell our dataset to read this XML file. This loads each one of those Products into the data set. We can now create a DataView off of the first (and only table) in our DataSet. Lastly we tell the view to sort itself based on the ProductID value. What we end up with is the entire XML file stored in a easy to query way in a DataView.
Now if we jump to where this is used in our program (around line 46) you will see the following code:
indexData = dvProducts.Find(strInput) If indexData = -1 Then Console.WriteLine("No product found.") Else Console.Write("Product Name: ") Console.WriteLine(dvProducts(indexData)("ProductName")) Console.Write("Quantity Per Unit: ") Console.WriteLine(dvProducts(indexData)("QuantityPerUnit")) ...
The first line of this code simply queries our products DataView to see if we have one with the specified Id. If we don’t we tell the user that but if we do we are off and rolling. Notice (in the Else portion of our code) that we write the label “Product Name: “ then we have this line:
So we already know what the WriteLine does (it will write out whatever text we tell it to). Then we see we are writing text from our dvProducts variable. We are accessing this view at a specified index (our indexData variable). This will be the index of the data that we found when we did the dvProducts.Find above. So if for example the id entered is the 4th product listed in our XML file the indexData variable will be 3 (since indexes are 0 based). The second thing we specify is the field name that we want to query. In this case we want to spit out the ProductName field. So if our indexData variable was 5 and we were to say this line of code in english it would be: Go to the sixth product in our list of products and give me the value of the ProductName field – write this out to the user.
This little 100 line program does an a lot. It is a great example of a simple console application. It is also a simple example of how we can store data in an XML DataSet and easily retrieve it. It even shows us how we can use reflection to read a file we embedded in our program. Hopefully this will get you off and running creating some fun application that uses XML.