Creating XML Trees With The XmlTextWriter and XmlDocument Objects

Dynamically create well-formed XML documents in your ASP.NET scripts.

Reading And Writing

If you’ve been following past issues of this column, you’re probably already aware of the numerous things you can do with XML and the .NET framework. You already know that there are two ways XML can be parsed, either via the Document Object Model (DOM) or the Microsoft-inspired “pull” model; that each method has pros and cons; that the selection of a parsing technique depends largely on the application; and that the .NET framework today supports both parsing methods, making it a versatile and flexible tool for XML application development.

Now, reading XML data is only half of the puzzle. Take a minute to think about the developer who gets an XML feed from a third-party vendor and needs to rejigger this data into a new XML file based on a custom DTD or XML Schema. How does (s)he do this? Is it possible to write an XML file on-the-fly?

Well, guess what? Just as there are two classes for reading XML data, the .NET framework comes with two for writing XML as well. The first of these is the handy XmlTextWriter object, which lets you write XML at run-time, and the second is the XmlDocument object, which allows you create XML files on-the-fly.

Intrigued? Keep reading.

Spending Time In The Library

The XmlTextWriter object can best be considered as a counterpart to the XmlTextReader object, allowing you to perform the reverse function. The next example shows you how:

<%@ Page Language="C#" Debug="true" %>
<%@ import  namespace="System.Xml"%>
<html>
<head>
<script runat="server">
void Page_Load() {

	// initialize a XmlTextWriter object
 	XmlTextWriter objXmlWriter = null;

	// location to the XML file to write
	String strXmlFile = "E:/Inetpub/wwwroot/xml/library.xml";

	// start the "try" block
	try {

		objXmlWriter = new XmlTextWriter (strXmlFile , null);

		// start writing the XML document
		objXmlWriter.WriteStartDocument(false);

		// start with the root element
		objXmlWriter.WriteStartElement("library");

		// first child element
		objXmlWriter.WriteStartElement("book", null);

		// add an attribute
		objXmlWriter.WriteAttributeString("bkid","MFRE001");

		// some text
		objXmlWriter.WriteElementString("title", "XML and PHP");

		// back to the root element
		// closing each element written above
		// one at a time
		objXmlWriter.WriteEndElement();
		objXmlWriter.WriteEndElement();

		// flush the object and write the
		// XML data to the file
		objXmlWriter.Flush();

	} catch (XmlException e) {

		output.Text = "An XML Exception occurred: " + e.Message;

	} catch (Exception e) {

		output.Text = "A General Exception occurred: " + e.Message;

	} finally {

		// Close the XMLWriter object
		if(objXmlWriter != null) {
			objXmlWriter.Close();
		}
	}
}
</script>
</head>
<body>
<asp:label id="output" runat="server" text="It's all done!" />
</body>
</html>

Run this example in your browser, and you might see something like this:

A General Exception occurred: Access to the path "E:/Inetpub/wwwroot/xml/library.xml" is denied.

Don’t despair - this is just a matter of giving appropriate permissions on the target directory to the user. But which user?

According to the official ASP.NET documentation, the “ASP.NET V1 RTM now runs using a less privileged Windows account - registered as the ASPNET account on a local machine” (http://www.asp.net/security.aspx?tabindex=0&tabid=1).

So, all this means that you need to locate the “ASPNET” user in your user management control panel and give the corresponding user account permission to write to the target directory. Once that’s done, run the example again, and you will now see a more cheerful message:

It's all done.

In reality, the action takes place elsewhere…

Navigate to the location specified in the script and look for a file called “library.xml”. This is what it should look like.

<?xml version="1.0" standalone="no"?><library><book bkid="MFRE001"><title>XML and PHP</title></book></library>

At first glance, this is very unattractive to the naked eye. I will show you later how this can be formatted to look a little nicer. First, though, it’s time for a quick anatomy lesson on the code above.

Breaking It Down

Here is a step-by-step explanation of the code listing on the previous page:

  1. The first step is to import all the classes required for the application. I’ll begin with the .NET libraries for the XML parser:
<%@ import  namespace="System.Xml"%>
  1. Within the Page_Load() function, I start by defining some variables and objects. The first is a local instance of the XmlTextWriter object, and the second is a string variable to store the location of the XML file. Note that you must give an absolute file path here (a relative path or a URL won’t work).
<%
	// initialize a XmlTextWriter object
 	XmlTextWriter objXmlWriter = null;

	// location to the XML file to write
	String strXmlFile = "E:/Inetpub/wwwroot/xml/library.xml";
%>
  1. Within an efficient little “try-catch” block, I now create an instance of the XmlTextWriter object, and begin writing the XML document instance by invoking the WriteStartDocument() method. This writes the opening XML declaration to the file.
<%
		objXmlWriter = new XmlTextWriter(strXmlFile , null);

		// start writing the XML document
		objXmlWriter.WriteStartDocument(false);
%>
  1. Next comes the (slow!) process of building the XML document by adding elements to it one-by-one using the WriteStartElement() method. This method takes only one argument - the element name - and hence cannot be used to write elements that contain character data.

The mirror image of the WriteStartElement() method is the WriteEndElement() method, which takes care of writing corresponding end elements to the XML document. Note that it is essential to get the order of method calls correct here, or else your XML output will not be well-formed…and we all know what a sin that is!

<%

	// start with the root element
	objXmlWriter.WriteStartElement("library");

	// first child element
	objXmlWriter.WriteStartElement("book", null);

	// more of the same

	// traverse back to the root element
	// closing each element written above
	// one at a time
	objXmlWriter.WriteEndElement();
	objXmlWriter.WriteEndElement();
%>
  1. Of course, writing elements without content may be a great deal of fun, but it isn’t actually very useful…which is why there are also some methods that actually write data into the XML file.

First, the WriteElementString() method, which requires two parameters: the name of the element and the data to be contained within it. Note that you don’t have to worry about closing elements written in this manner - the WriteElementString() method does all the work for you!

<%
	// first child element
	objXmlWriter.WriteStartElement("book", null);

	// add an attribute
	objXmlWriter.WriteAttributeString("bkid"," MFRE001");

	// an element with some text
	objXmlWriter.WriteElementString("title", "XML and PHP");

%>

What about attributes, you ask? No sweat, the XmlTextWriter class comes equipped with a handy WriteAttributeString() method for just that purpose. For example, the code above uses this method to add a “bkid” attribute to the <book> element.

  1. To wrap things up, the Flush() method actually writes the XML data stream that has been building in memory to a file. This is followed by a set of “catch” block to trap errors and gracefully exit, and a “finally” block that closes the XmlTextWriter object and frees up system resources for other activities.
<%

try {

		// snip

		// flush the object and write the
		// XML data to the file
		objXmlWriter.Flush();

	} catch (XmlException e) {

		output.Text = "An XML Exception occurred: " + e.Message;

	} catch (Exception e) {

		output.Text = "A General Exception occurred: " + e.Message;

	} finally {

		// close the XMLWriter object
		if(objXmlWriter != null) {
			objXmlWriter.Close();
		}
	}
}

%>

The Real Thing

As you must have figured out by now, using the XmlTextWriter object is fairly easy. In the introductory example, I demonstrated how you can write an XML file without much fuss; in this next one, I’ll go much further, demonstrating how the writer’s built-in properties and methods can be used to write a “real” XML file.

<%@ Page Language="C#" Debug="true" %>
<%@ import  namespace="System.Xml"%>
<html>
<head>
<script runat="server">
void Page_Load() {

	// initialize a XmlTextWriter object
 	XmlTextWriter objXmlWriter = null;

	// path to the XML file
	String strXmlFile = "E:/Inetpub/wwwroot/xml/library.xml";

	// start the "try" block
	try {

		// create an instance of the XmlTextWriter object
		objXmlWriter = new XmlTextWriter (strXmlFile , null);

		// indent the output in the XML file
		objXmlWriter.Formatting = Formatting.Indented;

		// set the number of space to indent
		objXmlWriter.Indentation =  5;

		// start writing the XML document
		objXmlWriter.WriteStartDocument(false);

		// write a comment
		objXmlWriter.WriteComment("This is a list of the books written by Melonfire.");

		// start writing the elements
		objXmlWriter.WriteStartElement("library");
		objXmlWriter.WriteStartElement("book", null);
		objXmlWriter.WriteAttributeString("bkid","b1");

		objXmlWriter.WriteElementString("title", "XML and PHP");
		objXmlWriter.WriteElementString("author", "Vikram Vaswani");

		objXmlWriter.WriteStartElement("description", null);
		objXmlWriter.WriteCData("Learn to manage your XML data with PHP");
		objXmlWriter.WriteEndElement();

		objXmlWriter.WriteStartElement("price", null);
		objXmlWriter.WriteAttributeString("currency","USD");
		objXmlWriter.WriteString("24.95");
		objXmlWriter.WriteEndElement();


		// close each element
		objXmlWriter.WriteEndElement();	// the "book" element
		objXmlWriter.WriteEndElement(); 	// the "library" element

		// flush and write XML data to the file
		objXmlWriter.Flush();

	} catch (XmlException e) {

		output.Text = "An XML Exception occurred: " + e.Message;

	} catch (Exception e) {

		output.Text = "A General Exception occurred: " + e.Message;

	} finally {

		// close the XMLWriter object
		if(objXmlWriter != null) {
			objXmlWriter.Close();
		}
	}
}
</script>
</head>
<body>
<asp:label id="output" runat="server" text="It's all done." />
</body>
</html>

Here’s the XML output generated by the above code listing.

<?xml version="1.0" standalone="no"?>
<!--This is a list of the books written by Melonfire.-->
<library>
     <book bkid="b1">
          <title>XML and PHP</title>
          <author>Vikram Vaswani</author>
          <description><![CDATA[ Learn to manage your XML data with PHP ]]></description>
          <price currency="USD">24.95</price>
     </book>
</library>

Looks a lot neater now, doesn’t it?

Let’s now look closely at the changes that I made to the first example to bring about this amazing transformation:

<%

	// create an instance of the XmlTextWriter object
	objXmlWriter = new XmlTextWriter (strXmlFile , null);

	// indent the output in the XML file
	objXmlWriter.Formatting = Formatting.Indented;

	// set the number of space to indent
	objXmlWriter.Indentation =  5;

%>

First up, the “Formatting” property of the XmlTextWriter object. If this property is set to “Formatting.Indented”, the XML output created by the class is indented (you can also use the “Indentation” property to control the amount of indentation, you control freak, you!).

<%

	// write a comment
	objXmlWriter.WriteComment("This is a list of the books written by Melonfire.");

%>

It’s obvious that the WriteComment() method is used to insert comments (hopefully meaningful) into the XML file. A good practice in general, this becomes a necessity if your XML file is widely distributed.

<%

	objXmlWriter.WriteElementString("title", "XML and PHP");
	objXmlWriter.WriteElementString("author", "Vikram Vaswani");

	objXmlWriter.WriteStartElement("description", null);
	objXmlWriter.WriteCData("Learn to manage your XML data with PHP");
	objXmlWriter.WriteEndElement();

	objXmlWriter.WriteStartElement("price", null);
	objXmlWriter.WriteAttributeString("currency","USD");
	objXmlWriter.WriteString("24.95");
	objXmlWriter.WriteEndElement();

%>

As you can see from the above, the <title> and <author> elements have been created using the WriteElementString() I showed you earlier. However, when it comes to more descriptive text, which is better stored as a CDATA element, you might want to use the WriteCData() method instead.

If you need to introduce an attribute at the last level of the XML hierarchy, opt for

<%

	objXmlWriter.WriteStartElement("price", null);
	objXmlWriter.WriteAttributeString("currency","USD");
	objXmlWriter.WriteString("24.95");
	objXmlWriter.WriteEndElement();


%>

Here, things start with a call to the WriteStartElement() method to write the starting element <price>. Now, I can introduce the “currency” attribute by invoking WriteAttributeString(), and write a value to it with the WriteString() method. The WriteEndElement() method wraps things up neatly by closing the element.

Walking the DOM

Now, you’ve seen in previous issues of this column how the XmlDocument object can read an XML file, build a tree to represent the structures found within it, and expose object methods and properties to manipulate them. What you have not yet seen is that this same object can be used to build a complete XML DOM tree in memory and then write it to a file. Take a look at the next example, which demonstrates this:

<%@ Page Language="C#" Debug="true" %>
<%@ import  namespace="System.Xml"%>
<html>
<head>
<script runat="server">

XmlElement MyElement(XmlDocument objXmlDocument, String strElementName, String strElementText) {

		XmlElement objElement = objXmlDocument.CreateElement(strElementName,null);
		objElement.AppendChild(objXmlDocument.CreateTextNode(strElementText));
		return objElement;

}

void Page_Load() {

	// initialize a XmlTextWriter object
 	XmlDocument objXmlDocument = null;

	// path to the XML file to write
	String strXmlFile = "E:/Inetpub/wwwroot/xml/library.xml";

	// start the "try" block
	try {

		// instantiate an XmlDocument object
		objXmlDocument = new XmlDocument();

		// create an XmlDeclaration object
		// and append it to XmlDocument object
		XmlDeclaration objXmlDec = objXmlDocument.CreateXmlDeclaration("1.0", null, "no");
		objXmlDocument.AppendChild(objXmlDec);

		// create a root level element
		XmlElement objRootElement = objXmlDocument.CreateElement("library",null);

		// create first level element
		XmlElement objElementLeveOne = objXmlDocument.CreateElement("book",null);

		// append elements at second level to the first level element
		objElementLeveOne.AppendChild(MyElement(objXmlDocument, "title","XML and PHP"));
		objElementLeveOne.AppendChild(MyElement(objXmlDocument, "author","Vikram Vaswani"));
		objElementLeveOne.AppendChild(MyElement(objXmlDocument, "description","Learn to manage your XML data with PHP"));
		objElementLeveOne.AppendChild(MyElement(objXmlDocument, "price","24.95"));

		// append first level to the root element
		objRootElement.AppendChild(objElementLeveOne);

		// append the entire hierarchy built above to the XMLDocument object
		objXmlDocument.AppendChild(objRootElement);

		// save the file
		objXmlDocument.Save(strXmlFile);

	} catch (XmlException e) {

		output.Text = "An XML Exception occurred: " + e.Message;

	} catch (Exception e) {

		output.Text = "A General Exception occurred: " + e.Message;

	} finally {

		// close the XmlDocument object
		if(objXmlDocument != null) {
			objXmlDocument = null;
		}
	}
}
</script>
</head>
<body>
<asp:label id="output" runat="server" text="It's all done." />
</body>
</html>

Here’s what the resulting XML file should look like.

<?xml version="1.0" standalone="no"?>
<library>
  <book bkid="MFRE001">
    <title>XML and PHP</title>
    <author>Vikram Vaswani</author>
    <description>Learn to manage your XML data with PHP</description>
    <price>24.95</price>
  </book>
</library>

Just the way I like it.

Let’s see how our ASP.NET script generated this output:

  1. As usual, the first step is to import the .NET libraries for the XML parser:
<%@ import  namespace="System.Xml"%>
  1. Within the Page_Load() function, I have defined some variables and objects - a local instance of the XmlDocument object and a string variable to store the location of the XML file. Note that here too, you have to give an absolute file path - no URLs allowed!
<%
	// initialize a XmlTextWriter object
 	XmlDocument objXmlDocument = null;

	// path to the XML file to write
	String strXmlFile = "E:/Inetpub/wwwroot/xml/library.xml";
%>
  1. The code snippet starts with the instantiation of the XmlDocument object that will allow me to build the XML tree in memory. I begin the process by creating an XmlDeclaration object, representing the XML prologue at the top of the document.

The XmlDocument object comes with an AppendChild() method - I will be using this method repeatedly - to attach the object (in this case, the XmlDeclaration object) passed as input to the DOM tree.

<%

	// instantiate an XmlDocument object
	objXmlDocument = new XmlDocument();

	// create an XmlDeclaration object
	// and append it to XmlDocument object
	XmlDeclaration objXmlDec = objXmlDocument.CreateXmlDeclaration("1.0", null, "no");
	objXmlDocument.AppendChild(objXmlDec);

%>
  1. You already know that the DOM revolves around a tree structure that is made up of hierarchical layers of nodes sharing a parent-child relationship between themselves. Building such a tree in memory requires a similar approach - first create an XmlElement object using the CreateElement() method of the XmlDocument object, then attach it to its parent by using the AppendChild() method. This process is demonstrated below:
<%

	// create a root level element
	XmlElement objRootElement = objXmlDocument.CreateElement("library",null);

	// create first level element
	XmlElement objElementLeveOne = 	objXmlDocument.CreateElement("book",null);

%>
  1. Why only use AppendChild() on objects? The XmlElement object comes with a similar method that allows you to easily attach children to an existing element. I’ve used this knowledge to add a second level to my DOM tree, as below:
<%

	// append elements at second level to first level element
	objElementLeveOne.AppendChild(MyElement(objXmlDocument, "title","XML and PHP"));
	objElementLeveOne.AppendChild(MyElement(objXmlDocument, "author","Vikram Vaswani"));
	objElementLeveOne.AppendChild(MyElement(objXmlDocument, "description","Learn to manage your XML data with PHP"));
	objElementLeveOne.AppendChild(MyElement(objXmlDocument, "price","24.95"));

%>

Since I plan to add four children to the <book> element (and you might want to add many more in real life), it makes sense to write a simple function that will do the hard work of creating an element and its data. That’s where my MyElement() function comes in. Take a closer look at this to see how it works.

<%

XmlElement MyElement(XmlDocument objXmlDocument, String strElementName, String strElementText) {

	XmlElement objElement = objXmlDocument.CreateElement(strElementName,null);
	objElement.AppendChild(objXmlDocument.CreateTextNode(strElementText));
	return objElement;
}

%>

This custom MyElement() function takes three parameters - the XmlDocument object, the name of the element to be created and the data for that element. The function first uses the CreateElement() method to create an XmlElement object, and the CreateTextNode() method to insert a text node at this point. Once its job is complete, the function returns the XmlElement object to the main Page_Load() function and the script continues executing - except, of course, that the objElementLeveOne object is now populated with four new child elements.

  1. In this manner, I keep append objects to their respective parents in a recursive manner, until the root element is reached. The Save() method is now used to write the entire tree to a flat-file, as shown below:
<%

	// append first level to the root element
	objRootElement.AppendChild(objElementLeveOne);

	// append the entire hierarchy built above to our XMLDocument object
	objXmlDocument.AppendChild(objRootElement);

	// save to a file
	objXmlDocument.Save(strXmlFile);

%>

The mandatory “try-catch” blocks trap unforeseen errors, and free up memory associated with the objects created in the script.

Adding More

Now, you’ve just seen how the XmlDocument object can be easily manipulated to write an XML file. However, the example on the previous page didn’t mention adding attributes. And with good reason - adding that particular capability is no small task. But hey, I did it for you anyway…

<%@ Page Language="C#" Debug="true" %>
<%@ import  namespace="System.Xml"%>
<%@ import  namespace="System.Collections"%>
<html>
<head>
<script runat="server">

XmlElement MyElement(XmlDocument objXmlDocument, String strElementName, String strElementText, Hashtable htAttrs) {

		XmlElement objElement = objXmlDocument.CreateElement(strElementName,null);
		if(htAttrs != null && htAttrs.Count != 0) {
			IDictionaryEnumerator enumAttr = htAttrs.GetEnumerator();
			while (enumAttr.MoveNext()) {
				objElement.SetAttribute(enumAttr.Key.ToString(),enumAttr.Value.ToString());
			}
		}
		objElement.AppendChild(objXmlDocument.CreateTextNode(strElementText));
		return objElement;

}

void Page_Load() {

	// initialize an XmlTextWriter object
 	XmlDocument objXmlDocument = null;

	// path to the XML file
	String strXmlFile = " E:/Inetpub/wwwroot/xml/library.xml ";

	// start the "try" block
	try {

		// instantiate an XmlDocument object
		objXmlDocument = new XmlDocument();

		// create an XmlDeclaration object
		// and append it to XmlDocument object
		XmlDeclaration objXmlDec = objXmlDocument.CreateXmlDeclaration("1.0", null, "no");
		objXmlDocument.AppendChild(objXmlDec);

		// create a root element
		XmlElement objRootElement = objXmlDocument.CreateElement("library",null);

		// create first level element
		XmlElement objElementLeveOne = objXmlDocument.CreateElement("book",null);
		objElementLeveOne.SetAttribute("bkid","MFRE001");

		// append elements at second level to first level element
		objElementLeveOne.AppendChild(MyElement(objXmlDocument, "title","XML and PHP", null));
		objElementLeveOne.AppendChild(MyElement(objXmlDocument, "author","Vikram Vaswani", null));
		objElementLeveOne.AppendChild(MyElement(objXmlDocument, "description","Learn to manage your XML data with PHP", null));

		// define an Hashtable to store
		// attribute name(s) and value(s)
		Hashtable htAttrs = new Hashtable();
		htAttrs.Add("currency", "USD");

		objElementLeveOne.AppendChild(MyElement(objXmlDocument, "price","24.95",htAttrs));

		// clear the Hashtable and
		// store new attribute name(s) and value(s)
		htAttrs.Clear();
		htAttrs.Add("reorder", "10");
		htAttrs.Add("maximum", "200");

		objElementLeveOne.AppendChild(MyElement(objXmlDocument, "quantity","150",htAttrs));


		// append first level to ROOT element
		objRootElement.AppendChild(objElementLeveOne);

		// append the entire hierarchy built above to XMLDocument object
		objXmlDocument.AppendChild(objRootElement);

		// save file
		objXmlDocument.Save(strXmlFile);

	} catch (XmlException e) {

		output.Text = "An XML Exception occurred: " + e.Message;

	} catch (Exception e) {

		output.Text = "A General Exception occurred: " + e.Message;

	} finally {

		// close the XmlDocument object
		if(objXmlDocument != null) {
			objXmlDocument = null;
		}
	}
}
</script>
</head>
<body>
<asp:label id="output" runat="server" text="It's all done." />
</body>
</html>

Here’s what the output looks like:

<?xml version="1.0" standalone="no"?>
<library>
  <book bkid="MFRE001">
    <title>XML and PHP</title>
    <author>Vikram Vaswani</author>
    <description>Learn to manage your XML data with PHP</description>
    <price currency="USD">24.95</price>
    <quantity maximum="200" reorder="10">150</quantity>
  </book>
</library>

First, let me highlight the code that handles adding attributes to elements. The process is pretty straightforward via the SetAttribute() method of the XmlElement object. As seen below, this method takes two parameters: the name of the attribute and its value.

<%

// create first level element
XmlElement objElementLeveOne = objXmlDocument.CreateElement("book",null);
objElementLeveOne.SetAttribute("bkid","MFRE001");

%>

Things become more interesting when it comes to rewriting the custom MyElement() method to support this. Two important things to keep in mind here: attributes are optional, and it should be possible to add more than one attribute at a time to an element. This is where the Hashtable, an object belonging to the System.Collections library comes in handy, as its ability to store key-value pairs maps very well into my requirements here. Take a look:

<%

// define an Hashtable to store
// the attribute name(s) and value(s)
Hashtable htAttrs = new Hashtable();
htAttrs.Add("currency", "USD");

objElementLeveOne.AppendChild(MyElement(objXmlDocument, "price","24.95",htAttrs));

// clear the above Hashtable and
// store new attribute name(s) and value(s)
htAttrs.Clear();
htAttrs.Add("reorder", "10");
htAttrs.Add("maximum", "200");

objElementLeveOne.AppendChild(MyElement(objXmlDocument, "quantity","150",htAttrs));

%>

Once the attribute-value pairs have been stored in a Hashtable, it’s time to pull them out and append them to their respective elements. This calls for an update to the MyElement() function defined earlier:

<%

XmlElement MyElement(XmlDocument objXmlDocument, String strElementName, String strElementText, Hashtable htAttrs) {

	XmlElement objElement = objXmlDocument.CreateElement(strElementName,null);

	// check if the htAttrs Hashtable has been passed
if(htAttrs != null && htAttrs.Count != 0) {

		// get an Enumerator to iterate through our Hashtable
		IDictionaryEnumerator enumAttr = htAttrs.GetEnumerator();
		while (enumAttr.MoveNext()) {
objElement.SetAttribute(enumAttr.Key.ToString(),enumAttr.Value.ToString());
		}
	}

	objElement.AppendChild(objXmlDocument.CreateTextNode(strElementText));		return objElement;
}

%>

The first step is, obviously, to alter the function signature to support a fourth input parameter, the Hashtable containing the attributes and values. Once that’s done, it’s necessary to check if this Hashtable contains any items at all (remember, attributes are optional) via its “Count” property. If it does, the GetEnumerator() method can be used to create an IDictionaryEnumerator to iterate over the Hashtable.

Now, all that remain is the actual task of iterating over the Hashtable - this is possible using the MoveNext() method of the enumerator. You can easily retrieve each name-value pair using the “Key” and “Value” properties, convert the values to strings with the ToString() function, and set them with the SetAttribute() method.

Phew!

Linking Out

And that’s about it. Over the last few pages, I gave you an introduction to the XmlTextWriter object, which allows you to write XML using straightforward syntax, and showed you how to use it to create a well-formed XML file. This was followed by a set of examples using the XmlDocument object. As you have already seen, this object is designed to read an XML file, build a tree to represent the structures found within it, and expose object methods and properties to manipulate them. Today, I extended your understanding of this object and showed how you can use it to create a DOM tree in memory using the different methods available in the .NET framework.

Each example demonstrated the concept of creating nodes, and how to use the DOM to build an XML document right from the root element to any child node at any depth. The examples also addressed the issue of dynamically adding attributes and CDATA to your XML tree, showing you how to add these important XML constructs to your DOM trees.

You can read more about the XmlTextWriter object at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemXmlXmlTextWriterClassTopic.asp, and the XMLDocument object at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemXmlXmlDocumentClassTopic.asp

Until next time…see ya!

Note: Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!

This article was first published on 02 Mar 2004.