DataGrids, DataSets, and XML StringsBy Anthony Hart
Not long ago, Scott Mitchell wrote an informative article on how to populate a DataSet using an XML file (see XML, the DataSet, and a DataGrid). He also showed the converse of that process, namely, writing the XML representation of a DataSet to disk using the DataSet's
WriteXmlmethod. There are many uses for such an approach and I was happy to have found Scott's wonderful article on the subject.
Unfortunately for me, however, I often find myself dealing with XML in a string format rather than XML read from a file. This article will build on what Scott explained in his article, illustrating how to accomplish the same task with an XML string.
The End Game
Before we examine how we're going to accomplish converting database output to and from an XML string, let's look at what our output should be. Ideally, when the user first visits the Web page a database access will occur grabbing information and storing it in a DataSet. The user will then have two options, to either view the data in a DataGrid or to view the XML representation of the data (the default choice being the DataGrid display). When the DataGrid display is selected, the DataSet will be bound to a DataGrid Web control, displaying the database output in a visually appealing way. (Be sure to read An Extensive Examination of the DataGrid Web Control for more information on using the DataGrid.) When the "View as XML" option is selected, the user will see the database output represented as textual XML.
This approach is similar to the technique Scott Mitchell used in his XML, the DataSet, and a DataGrid article, the main difference being that instead of persisting the DataSet's XML to disk, we are simply storing it in a page-level string variable. The screenshot to the above right shows the view of the page when the user has opted to view the database's result as a DataGrid (note that this is the default view and will be the view displayed upon the first visit to the page). By clicking the buttons at the top, the user can toggle between the DataGrid view and the XML view, which is shown to the left:
Getting Set Up
In the code available for download at the end of this article, you will notice that I have two global variables declared. One is my connection string pointing to the Northwind database. You may use whichever database you wish for this example, because we won't be modifying any data � just displaying it. The other global variable will be used to store my XML string. (Note that you may want to store information like connection strings in your Web.config file - see Specifying Configuration Settings in Web.config for more information.)
These two variables are declared in the following code block:
Please notice, too, the Label control (
lblHidden) found in the page body. This Label
control will be used as a placeholder of sorts, to hold the XML string across postbacks to the page
so that we only need to hit the database on the first visit to the page. Subsequent postbacks
will not need to hit the database because we will be storing the XML output in this Label control.
This Label control initially has its
Visible property is set to False because upon the user's
first visit to the page we want to show the DataGrid display as opposed to the XML display. (Using the
Label control as a cross-postback placeholder is not the only possible way to persist data across
page postbacks: we could have used session variables (not the best choice) or the ViewState (a better
choice). Essentially this Label-placeholder trick is synonymous to using the ViewState, except this technique uses the
The first thing we do when the page is loaded is grab whatever string value is currently stored in the invisible Label and stuff it into our global XML string variable.
Next, we grab some data from the database, stuff it into a DataSet object, and then bind the DataGrid to the DataSet. This will give us our initial view of the populated DataGrid.
Getting XML From A DataSet
When the "DataSet To XML" button is clicked, a call is made to the
DisplayXMLFromDataSet()procedure. The gist of that procedure is found below.
The first time we submit the form we don't have any XML data, so we obtain it by calling the
GetXMLFromDataSet() function. The code snippet below shows how we generate the XML string.
Here we see that we must populate a DataSet and then call its
GetXml() method in order to
produce its XML representation (the
GetXml() method of the DataSet was discussed in
the XML, the DataSet, and a DataGrid article). Obviously, we
don't want to have to go to the database and create a new DataSet object every time the form is submitted,
so we only execute the
GetXMLFromDataSet() function if the global XML string variable is
The next thing we do is hide the DataGrid and show the Label that we will use for displaying the XML
string. We then feed it the XML obtained to be displayed on the screen. Also notice that the last
action performed is to set the
Text property of the invisible Label to the value of the
XML string we just generated. This will provide us with an XML string when the Web form is posted back,
thus avoiding another trip to the database.
The main piece of code to remember in this part of the process is the call to the
GetXml() method of the DataSet. In Scott's article, he showed us how to use the DataSet's
WriteXML() method to save the XML to a file. For our purposes, however, we just want to
persist the XML string for later use without placing it into a file.
Getting A DataSet From An XML String
A click on the "XML To DataSet" button will kick off a process opposite of that just illustrated. In other words, we will take an XML string and use it to populate a DataSet and then bind the DataSet to the DataGrid to display the data obtained from the XML string. When the button is clicked, a call is made to the
The procedure is sent the XML string that we had stored in the hidden Label object. The variable is sent by-reference, by the way, so any changes made to it within the procedure will also be applied to it elsewhere, but that, too, is a topic for another article.
In looking at the code snippet above, we see that the XML string is tested to see if we need to make
a trip to the database or not. In this case, we already have some XML, so we don't need to query the
database. Next, we create a
StringReader object and fill it with our XML string. In
Scott's article, we learned that the
ReadXml() method of the DataSet object accepts a
string as a parameter that indicates a path from which to read an XML file. In our case, though, we
want to use a string of XML, not an XML file, so we obviously have no path to feed to the
ReadXml() method. Well, it just so happens that
ReadXml() is an overloaded
method and can accept a
TextReader object (as well as quite a few other objects) instead
of a path string.
TextReader class is an abstract class, meaning, for our purposes, that it can't be
used directly, but must be inherited from. Abstract classes comprise yet another topic for another
article, but suffice it to say that .NET provides a handy object that is already inherited from the
TextReader class: the
StringReader. Since it is a "descendant" of a
TextReader, it can be used as a parameter to send to the
That makes it very useful to us in this case, because all we have to do is feed the
our XML string and then send it into the
ReadXml() method to populate the DataSet.
Once we've filled the DataSet with the XML data, we hide the XML Label and show the DataGrid and bind the DataSet to it and display the data. And with that, we're done!
.NET has provided us with many useful tools to assist us in working with XML data. As Scott Mitchell has shown us in a previous article, we can use a combination of DataSets and DataGrids to present data found in XML files. In the example illustrated above, we see that we are not limited to the presentation of XML files alone, but we can also use data found in XML strings. .NET is indeed a veritable cornucopia of tools and possibilities.