HELP
Richard Mansfield
Printing This Lesson
Select what you’d like to include when you print, and then click the Print Lesson button:
Text, images and activities (IE users only)
Text and images
Text only
Saving This Lesson
For instructions on saving this lesson (shown below), please select the browser you're using.
Introduction
Welcome to our final lesson in this course! Today, we'll explore the two primary ways to access an XML file: DOM and SAX. You'll discover the uses and advantages of each approach, although it's likely you'll stick with DOM for most of your XML work—at least in the near future.
You'll also transform the cookbook program into a more sophisticated XML database manager. You'll reuse some code in the cookbook program, but you'll also learn new techniques such as making a group of controls share a single event. Finally, you'll see how to manage more complex XML—both in a data-entry program and in an associated data management program that does for a coin collector what the cookbook does for a chef.
The XML file in this lesson includes 13 child elements, so both data entry and data management are more complicated than the cookbook with its two child elements. The coin collection program also displays optional photos, drawings, or other graphics for each coin.
But if coin collecting isn't your thing, with only a few changes to the code, you can transform the program into a database for any other kind of collection—antiques, comics, DVDs, family history scrapbook, cards, books, or butterflies.
Ready to get started? Let's dive in.
Understanding DOM and SAX
XML programming comes in two different flavors: random access and sequential access. In fact, you'll find that these two ways to access information also appear in many real-world situations.
Think about Netflix for a moment. It offers two distinct ways to view a movie: They will mail you a DVD disk, or they stream the movie over the Internet.
These two methods differ in several ways:
DVD
Streaming
You can manage XML data in these same two ways: the DOM (Document Object Model) approach is like a DVD, and the SAX (Simple API for XML) approach streams like a tape. You can use either technique in your VB programs. (API stands for Application Programming Interface.)
As you'd expect, the DOM loads the entire XML document file into your computer's memory, like loading a DVD movie into a player—the entire movie goes in. DOM builds a tree structure in memory. This means you can instantly jump around, back and forth, to access any location in the document. You can use XPath and XSL techniques when a DOM tree is in memory.
But there's a cost. Recall that XML is a verbose data storage system—all those descriptive element tags take up space. What's more, the tree that DOM builds in memory is about 150% larger than the XML data file that it comes from. So we're not even talking about a one-to-one copy of the XML disk file, but an inflated copy. A DOM tree is specially optimized for XPath queries and XSL transformations.
In this course, we've used DOM techniques almost exclusively because of its power and flexibility. Also, our cookbook, quiz, and coin collection programs' memory requirements are modest. Here's an example of a DOM statement from the cookbook. This creates the DOM tree in memory:
doc.Load(RecipesFilePath)
SAX, by contrast, streams only a small portion of the XML file into the computer's memory at any given time. And there's no initial loading, parsing, or tree building. SAX is most useful when you're working with large XML files like Amazon's immense database, or the NSA's mega-storage needs.
People usually stick with DOM unless they need to work with a gigantic XML document, and then they switch to SAX.
Of course SAX, too, has its drawbacks. It's less flexible than DOM, because it mainly reads forward (sequentially) through the XML data. It's like you're watching a parade pass by. Parades don't easily rewind and march backward. And a spectator can't quickly move to any location in a parade.
Nevertheless, for some tasks, such as searching for a single element in a huge file, you don't really need the power of DOM or its memory tree.
SAX Has Various Meanings
I'm using the term SAX loosely here. Technically, some implementations of SAX can rewind and perform other DOM-like maneuvers. And some DOM commands employ streamlined read-forward techniques.
But categories and implementations tend to break down on close inspection. IBM, for example, has developed a way to stream with XSL style sheets, and even offers what it calls "partially streaming mode."
Then there's the VB XMLNodeReader that we used in the cookbook's search feature. Although technically it's a DOM command (it reads a DOM tree in memory), it's still read-forward only. So it's a DOM command that behaves like a SAX command.
Even so, the terms DOM and SAX are useful to distinguish the two main techniques you can use to manage XML data.
Practicing the SAX
We introduced the SAX StreamWriter command in the Quiz Data Entry program in Lesson 11. But now let's take a quick look at a few additional SAX-type commands, so you'll have some experience with them if you ever need to work with large XML files.
VB's XMLTextWriter object, although similar to the StreamWriter, is more XML-specific. Here's an example that uses the XMLTextWriter to create a new XML document (to see and test this code, double-click the SAX.sln file in the C:\XML L12 Finished\SAX example folder):
This VB code is mostly self-explanatory. The WriteStartDocument command inserts the usual XML file declaration. The IO.File.ReadAllText command does just what it says: gives you the complete contents of a text file. In this example, we display our new XML file to the user in this messagebox. Press F5 in VB to run the SAX example program, and you'll see this result:
Try your hand at this quick game before we continue on!
Matchbox Game
All right, we're ready to being today's programming.
We'll create two programs in this lesson: a coin collection notebook and a data-entry program where the user enters the information about each coin.
We didn't need a data entry program for the cookbook program because there were only two elements for each recipe: the title and the instructions. You just find a recipe on the Internet (or type one into Notepad), and all you have to worry about is having the title on the first line, and everything else (the instructions) on the rest of the lines. There are only those two fields.
By contrast, we do need a data-entry program to make it easy for the user to type in the information about their coins. Why? Because there are 13 pieces of information—13 fields—for each coin! This many elements cries out for a form the typist can fill in. For one thing, we can label each field so the user doesn't get confused about what piece of information they're typing in.
So here's my version of an efficient data-entry form that the user can type data into for the coins in their collection.
Setting Things Up
Using Windows File Explorer, locate the C:\XML L12 Finished\Coin Collection Data Entry folder, and then double-click the Coin Collection Data Entry.sln filename to open this project in VB so you can follow along.
The code begins by referencing a couple of libraries. The IO namespace contains a StreamWriter object that we'll use to create the coin collection XML document.
As in the cookbook program, you next create two global variables: one to hold the location of the XML file and the other a DOM object variable named doc.
The Form_Load event then checks to see if it can find the coin collection.xml file. If it's on the hard drive, that means the user wants to add new coins to an existing collection. So the code jumps past the End If line and loads the DOM model of the collection into memory.
But if the coin collection.xml file doesn't already exist, that means the user is starting a whole new coin collection XML file, so we use a SAX StreamWriter to create a new XML document. This new XML file is a stub, containing only the bare necessities: the declaration line and the root element that I named <collection>.
The code then closes this stub file but immediately reopens it as a DOM document, ready for the user to add new coin entries to the database.
Finally, we display instructions to the user on how to enter new data. And we set the Finish button's tabstop to False. This means that pressing the Tab key will never move focus to the button that shuts down the program. Pressing the Tab key should only jump to the next field on the form (or move to the next, blank form if the user presses Tab in the final field (Quantity). We don't want the user to accidentally tab to the Exit button.
The program waits and does nothing until the user presses Tab in that final field, Quantity, triggering its Validating event:
The validation in this program only checks one thing: that the Description field has something in it. I decided that the Description field is the only field the user must fill in (you could require additional fields if you wish, or none). This code means "does not equal empty": <> "".
If things are fine and the description has some text in it, the program executes our SaveCurrentEntry sub. But if the Description field is empty, we display an InputBox to request that the user provide the required description.
When they type in a description, a "Thank you" message box lets them know that the program has successfully saved this coin to the database. Without that messagebox, the program would only display the next blank form. Users would be slightly astonished. They would wonder if the program had actually saved the coin. So by displaying the "Thank you" messagebox, we pause the program, letting the user see that the Description field is filled.
Understanding the InputBox
Messageboxes are great if you want to simply display some information to the user, or ask the user a Yes or No question. But if you need the user to type some text, you want to use an inputbox instead.
Like a messagebox, an inputbox comes in several versions. The one we're using here displays some instructions to the user, and then the user types in the coin description we asked for and clicks OK to submit the text. Our code then saves the user's text string to the Description.text property.
In other words, the description field now has some text in it so the program can move forward to the next blank page. (Or it can shut down if the user clicks the Finish button.)
Dealing With Redundancy: Only Six Commands in 58 Lines of Code
Now locate the SaveCurrentEntry event in the code window. Notice how repetitive much of this code is? Programmers often try to eliminate repetitive code like this by creating a loop and feeding data into that loop. But this redundant code does no harm and actually makes it easier to see what's going on here.
Take a look at this video where I explain how to deal with redundant code:
What about redundancies? What about repetitive code? Is that a problem? Well, it sure was several decades ago when computer memory was extremely expensive. Programmers would ruthlessly track down any repetitive code and put it in a loop or otherwise deal with it to make it take up less space, but these days, memory is not an issue anymore, in most programming, anyway.
But let's take a look at some redundant code that we have in our Coin Collection Data Entry program. This Sub SaveCurrentEntry executes when the user has filled in the data for one of their coins in their collection and wants to go to the next coin and fill in its data.
So, what we have to do is save the information on the form to the XML file, and these first 13 lines here of repetitive code do the same thing over and over again for each textbox. We create a new child element for each textbox and then copy the textboxes' contents into the XmlElement's InnerText. Then we append each of the child elements to the XML file using the AppendChild command and then save the whole thing down here in this line. And finally, we assign to each of the textboxes empty text. In other words, we make them blank, which to the user appears as if they've turned a page and are ready to fill in a new, blank empty form with the new coin's data.
To give you an idea of how to get rid of redundancy if you want to, let's take this block of 13 lines of code and reduce it to a simple loop. We'll delete it and replace it. Now, this loop has an interesting feature in it called Me.Controls, which is a collection of controls that Visual Basic maintains for every control on a given form. Our form has 13 textboxes, 13 associated labels, and a Finish button. These are all part of the control collection for this form, but we're only interested in dealing with the textboxes, so let's see how we do that.
First, we create a control object by dimming it here, and then for each control in Me.Controls— Me, remember, means the current form. So for every control on our form, if the type of control is a textbox, then—well, we created a textbox object temporarily here. And then we assign a blank empty text.
But as I say, for beginners, I don't think that redundancy should be very high on your list of things. You've got plenty of other issues to deal with in programming that are more significant, such as debugging and testing, than worrying about collapsing repetitive lines into loops.
END TRANSCRIPT
All right, it's your final XML Challenge! You learned the difference between the two main ways to manage an XML document. SAX streaming moves forward through the document. But the DOM approach builds a model of the entire XML document in the computer's memory, allowing you to skip around at will anywhere within that structure.
Take another look at the Coin Collection Data Entry program's code. Your challenge is to describe which technique I used in this code: Is it DOM or SAX?
It's both! If the user is creating a brand-new coin collection database, the Form_Load event uses streaming to start a new XML file:
But Form_Load employs DOM when it builds the XML model in memory:
And later, the program uses DOM commands such as CreateElement and AppendChild to transform the DOM model. So as you see, there's no problem if you want to employ both SAX and DOM techniques in the same program.
Building the Main Program
Time to design! Here's my design for the coin collection program's UI. But as always, you'll want to modify the look to suit yourself.
If anyone tells you that design isn't that important, you can remind them (in a kind way, of course) that Microsoft itself has announced that design will now be central to its future. As Microsoft Vice President Joe Belfiore said, "It used to be that engineers ruled the roost and engineers would bring in designers to make icons. It's changed now."
Clearly, it hasn't escaped Microsoft's attention that emphasis on design is largely responsible for Apple's huge success.
Using Windows File Explorer, locate the C:\XML L12 Finished\Coin Collection folder, and then double-click the Coin Collection.sln filename to open this project in VB so you can follow along.
So go ahead and add your own background image to the form, rearrange the buttons if you want, change the typeface, or make whatever other adjustments look good. And if somebody claims that you're just playing around, remind them that in these post-iPhone days, design is serious business.
In fact, it's such serious business, let's look at a few tips . . .
Design Tips
Let's Chat!
Most users appreciate a good visual design—both for its looks and for its efficiency. Choosing the right fontsize, for example, draws on both your aesthetic and practical skills. The editor's default fontsize (8) is simply too small for most people to comfortably read on most computer screens.
Are there any other properties that you often find yourself changing? Do you know of a good source on the Internet for form backgrounds? How do you feel about adding shadows under controls or under text? Do you prefer textures rather than photographs for background images? Pop over to the Discussion Area and share your ideas with your classmates.
Examining the Code
When you look at the Coin Collection program's code, you'll recognize parts of it. This is the cookbook program transformed into a coin scrapbook. Here's the initialization, the housekeeping preliminaries we need to do before displaying the form to the user:
With a couple of minor exceptions, this is identical to the code in the cookbook program. So you'll probably have little trouble reading it and understanding what it does.
Now, let's move on to the listbox's Click event.
Responding to the User's Click
When the user clicks a coin's description in the listbox, our job is to fetch the 12 other fields of data and display them (12 because there are 12 textboxes, plus that listbox entry):
Here we create an XPath query that specifies the particular coin element we're searching for:
The SelectedItem is the coin the user clicked in the listbox (the coin the user wants to see). It's the description element in the XML file for this particular coin. So we fetch this element from the XML document and assign it to our IndividualCoin variable:
IndividualCoin = root.SelectSingleNode(xpathTarget)
Now that we're located in the XML document at this coin's node (element), we copy the contents (InnerText) of each of the 12 child nodes into the textboxes so the user can see all the information about this coin. And if there's a picture of the coin, we display it, too. We'll explore how to display graphics shortly.
Let's look at adding a Delete feature.
Adding a Delete Feature
This sub deletes a coin from the collection. It also doesn't require much modification after copying it from the cookbook's delete button code:
All we do here is fetch whatever coin element (node) is currently displayed (currently selected in the listbox), and then we use the RemoveChild command to delete the entire element from the DOM model. We save the now-modified XML document to the hard drive, overwriting the old file. And finally, we remove this coin from the listbox.
Searching the Collection
As you know, VB, like most programming languages, can usually carry out a given task in several ways. The code for the search feature in the coin collection program differs from the search feature in the cookbook program. The cookbook uses the read-forward XMLNodeReader. In this program, we'll employ an XMLNodeList. Either approach works fine in either program:
The GetElementsByTagName command creates a collection of all the singlecoinentry elements, in other words, a collection of all the coins. Then, we loop through this collection until we locate a singlecoinentry element's InnerText that matches the search term the user typed in (txtSearch.Text). If a match is found, that coin is added to the listbox, and the variable named found is set to True.
What's most interesting here is this line of code:
s = SingleCoinEntry.InnerText
The InnerText command gives our program a copy of the contents of an element. In the cookbook program, we used this command twice: once to fetch a copy of a recipe title, and again to get a copy of that recipe's instructions. Neither of these elements had any children.
But here, we're getting a copy of the contents of an element that has 13 children, so what kind of content exactly do you get from a parent element? You get the entire contents of all the children in one big clump!
Here's what the InnerText command returns for my first coin element:
Gold 20 DollarSharp and solid coin1987375vfUS1902s$201
All 13 child elements' contents are fused together into a single string with no delimiters. Seems weird, but it's actually not a problem for our purposes.
Say the user typed VG as the search term. Our code just needs to find out if VG is somewhere in any of these child elements' contents. No need for delimiters. In fact, the InStr command doesn't even deal in delimiters. It merely tells you whether one string (txtSearch.Text) is located somewhere within another string (s):
InStr gives us a yes or no answer, and that's all we need to know to see if the user's search term is in this data.
All right, let's look at the descriptions . . .
Showing All the Descriptions
After the user does a search, the listbox isn't likely displaying all the coins in the collection. It's displaying only the subset of the coins that matched the user's search term. This btnShowAllDescriptions button is how the user can restore a complete list of all the coins.
I lifted this code directly from the cookbook program:
When the program displays search results, we change the backcolor of the listbox to beige. Then, when the user clicks the ShowAllDescriptions button, we need to change the color of the listbox back to its default gold color (I chose that color in the Properties window when creating the design). The Properties window displays the color as three RGB numbers, so I used the Color.FromArgb command to turn it gold.
Did I know about this Color.FromArgb command? Never heard of it until I Googled "vb net rgb."
Updating the XML Document
If the user changes any of the data about a coin, we must update the XML data file. The code that updates the coin collection program's data file is similar to the cookbook program code, with a couple of important exceptions. Let's take a look!
We're now dealing with 12 textboxes (fields), any of which the user can modify. (The 13th datum, the Description, is in the listbox and isn't modifiable by the user other than to delete the coin from the database.)
Updating the XML data file was simpler in the cookbook, because it has only those two fields—title and instructions. How can we easily handle 12 textbox events in our code without having to use 12 separate subs—one for each textbox? Luckily, you can write code in only one event but make it service all 12 textboxes at the same time.
You just list the controls you want serviced in the event's Handles clause, like this:
This one sub will now respond to the Leave events of every control named in its Handles clause. When any of their Leave events triggers, the program execution jumps to this TextFields_Leave sub.
Naming Custom Subs
I called this sub TextFields, but you can use any name you want. Naming your custom subs is like naming variables. When you create a sub of your own, you get to choose its name.
In this program, I named each textbox after its associated XML element's tag name. So we build a Handles clause by specifying all the textboxes: notes, dateofpurchase, and so on. But how will our code know which particular element of the 12 should be updated? The secret is in the sender object. It means: Which textbox's Leave event triggered and sent program execution here to this TextFields sub?
Sender contains the name of the textbox whose contents the user modified. So we create a variable I called strFieldName and then copy the name of the sender into that variable:
Then we fetch the contents of the sender textbox:
And then we store the contents into the appropriate child element:
IndividualCoin.Item(strFieldName).InnerText = strContents
Adding Graphics
We can improve this coin collection program by showing pictures of the coins. But you can't store these pictures in your XML file. As you've learned, XML almost never stores graphics in an XML document itself. One reason is that XML specializes in text (which uses up far less disk space than graphics). For example, the entire text of this lesson uses only 35 kilobytes, but a picture of a single coin uses 10 megabytes, 300 times more space.
And an even more important reason to leave graphics out of an XML document is that XML must be parsed (read and interpreted). If you embed bitmap images within the XML data, tasks like validation or rendering become difficult. As the parser reads through the bitmap, sooner or later random areas in these large bitmaps would resemble ordinary XML text, fooling the parser.
It's the old monkey story: Given enough random typing, monkeys would eventually produce the entire works of Shakespeare—along with every other book ever written or to be written in the future.
So instead of messing up the XML data by stuffing graphics into the XML file, separate graphics files hold the images. Here's one way in VB to fetch and show a graphics file. This code, at the end of the listbox's Click event, displays pictures of the coins:
Here's how this displays a picture. We store the picture's file path (the directory location plus its filename) in a variable called PicturePath. We can't just write the literal path into our code, because the filename is different for each picture. So the program must calculate the filename on the fly during execution and append it (using the & command) to the C:\xml L12 Finished\coin collection\ file path.
So you must store the photos in your XML L12 Finished\Coin Collection folder and name the picture files coinpicture1.png, coinpicture2.png, and so on.
The item currently selected in the listbox has a number, the SelectedIndex number. But listboxes start counting from 0, so the coin on the top of the list is index number 0, the next one down is 1, and so on. That's why we add 1 to the coin names (SelectedIndex + 1.ToString).
I'm using the high-resolution .png graphics file type. But if you want to use some other file type, just change .png in the code to .jpg or whatever your graphics file's extension is.
If a picture is found, it's loaded into our PictureBox control on the form. If no picture is found, the PictureBox's Image property is set to Nothing, so it goes blank. Did I know what command makes a PictureBox go blank? As usual, I didn't. An Internet search for "vb.net empty picture box" gave me the code sample I needed.
Why do I keep telling you I don't know how to do things in VB code? One of the main points I want you to take away from this course is that nobody expects you to already know how to write all the code in your programs. True, some fortunate people can remember everything, but most of us can't. That's why there are thesauruses, car repair manuals, cookbook programs, and code samples scattered all over the Internet.
So please remember that I wrote some of the code in this course by leaning heavily on Internet searches. And as your programming career continues, it's likely you will too.
Well, we've come to the end of the course now, and I hope you've enjoyed it as much as I have. I've gotten to know a number of you in the Discussion Area, and I feel confident that some are going to go on to become professional programmers. But even if you don't, I'd still encourage you to keep using your computer as a tool for programming, not just information consumption. Programming can be, as I hope you've learned in these past few weeks, not only easy, but extremely rewarding. So thank you for joining this course, and I hope it's been valuable to you
Summary
Congratulations! You're just about finished. Be sure to check out the Supplementary Material section for this lesson, as well as the FAQs, your final assignment, and quiz.
Any lingering questions? Don't hesitate to stop by the Discussion Area before you leave. Also, there's a Facebook page for this course. It's a good idea to participate in that group, because this is where you'll see your classmates again and also where you can get some answers to your future questions.
I hope you've enjoyed this course as much as I've enjoyed teaching it. XML's combination of simplicity and efficiency guarantees that it's going to be around for a long time. And you now have a firm foundation in the essentials of programming and managing this powerful technology!
Final Steps
Now that you've finished the last lesson, is there anything else to do? Yes, several things!
Other Courses
If you enjoyed this course, here are a few other online courses you might be interested in:
Introduction to Visual Basic
In this course, you'll learn how to write code for programs using Visual Basic, the most widely used programming language and development tool for creating Windows applications. The course covers the building blocks of programming, including using variables to store data, control structures, and loops. You'll also master the principles of object-oriented and event-driven programming that you can use not only with Visual Basic, but also with other programming languages you may want to learn.
Introduction to Java Programming
If you want to learn computer programming but don't have any prior experience, you'll enjoy a tour of Java, one of the most widely used computer languages in the world. It's a breeze to learn in a friendly and supportive environment. Start with the basics of program design and go on to write your own programs and integrate input and output, calculations, decision making, and loops. Build your knowledge and confidence with easy-to-understand examples and plenty of skill-building exercises. So whether you just want to try it out to see if you like it or plan on doing more with Java, this is a great place to start!
Introduction to Programming
Take your first steps toward a career as a computer programmer! Using Just BASIC, a free and simple programming language, you'll learn how to create and work with graphical user interfaces, controls, variables, arrays, conditional logic, and loops. You'll even dig into graphics and sound as you master basic programming concepts. In each lesson, you'll get hands-on practice as you write a working computer-game application. By the end of the course, you'll have the skills and confidence you need to program in BASIC and design your own custom applications for home, school, or work.
This Web page offers valuable suggestions for efficient UI design. You'll discover here why I put the Show All Descriptions button down next to the Search textbox (Rule #3) and why I displayed instructions for using the Coin Data Entry program up on the form's title bar (Rule #5). See if your UI follows these seven important guidelines!
Visit this site if you need further convincing—or ammunition to convince others—of the importance of making your UI look good. You'll find out why Apple's Mac designers made sure to round the corners of rectangles to avoid sharp corners. And you'll also discover why nobody would go to a nightclub designed solely by engineers!
Here's a link for DreamSpark, which we discuss in the FAQs for this lesson.
And here's the link for the setup application, also discussed in the FAQs.
Q: How can I give someone a copy of the cookbook program—or the quiz or coin collection? (Or some other program I write in the future?)
A: Excellent question! You can't just give them the .sln file, because VB programs also need all those code libraries like System.Xml and other support files not included within an .sln file.
Microsoft used to include a setup packaging application in the Express editions of VB. Unfortunately, that app is now only available in the retail version of VS.
So you have several options:
After I finished the Coin Collection program—or thought I finished it—I discovered that users might want one more field: CurrentValue. We have the PurchasePrice and SalePrice fields, but some collectors might also want to specify the likely current price they could get if they sold the coin.
So your assignment is to add a textbox named currentvalue to the form and modify the code to make this new textbox do its job. Go ahead and do that now!
You only need to make two changes in the code. Add the following highlighted code to the coin collection program:
And you'll need to add a currentvalue element to both the coin collection data entry program, and as a child element under each <singlecoinentry> element the coin collection.xml file.
Back to top