Sometimes when you're programming, you'll want to generate an HTML document. This may be because you're writing some sort of web app, or maybe you want your program to be able to output in a web-friendly format.

The String Concatenation Approach

Whatever your reason is for generating HTML, the best bet is your first prototype looked something like this:

(Aside: All this code is in VB.NET... the original VB.NET (i.e. not 2005 or later). It also assumes ASP.NET 1.1. This is because the client I work for still uses this technology, so all my experience is with it. The code should still be fine though, as all versions of .NET after 1.1 are more or less backwards compatible.)

' Run some query on the database.
Dim dataTable As DataTable = Query()

' Dump it into an HTML document.
Response.Write("<html>" + Environment.NewLine)
Response.Write("<head><title>Database Table</title></head>")
Response.Write(Environment.NewLine)
Response.Write("<body>" + Environment.NewLine)
Response.Write("<table>" + Environment.NewLine)

' Print the rows.
For Each row As DataRow In dataTable
  Response.Write("<tr>")
  ' Print the cells.
  For Each item As Object In row
    If IsDBNull(item) = False Then
      Response.Write("<td>" + CStr(item) + "</td>")
    Else
      Response.Write("<td>&nbsp;</td>")
    End If
  End For
  Response.Write("</tr>")
End For

Response.Write("</table>" + Environment.NewLine)
Response.Write("</body>" + Environment.NewLine)
Response.Write("</html>" + Environment.NewLine)

Now don't get me wrong, this code will do the trick. But as you write it, you start to feel a bit dirty. HTML is a language for representing hierarchies, yet you're concatenating strings. You start to feel like there's a more elegant way to do it, a way that takes advantage of the structure of HTML.

And there is.

The Programmatic Approach

Ok, so we want to take an approach that has some knowledge of the HTML we're writing. Enter XML. .NET uses XML for, among other things, it's Javadoc-like documentation generator and it's ASP.NET config files. With XML so prevalent in .NET, it's not surprising to discover that it's part of the standard library, in the namespace System.Xml.

So you're thinking "Cameron, who cares about XML, I want to make an HTML document!" Gear down, sugar plum, XML can still help! As you may or may not know, HTML (at least the XHTML dialects) is a reformulation of XML. That is, an XHTML document is an XML document. As a result, we can use .NET's built-in XML support to generate an HTML document.

Thus, if we want to write the same code in previous example in .NET XML, we would do the following. First, we would need to make a new XML document. That's easy enough:

Imports System.Xml

' Create a new XML document.
Dim xmlDoc As XmlDocument = New XmlDocument

Now we want to start writing some HTML. So let's create our html tag and add some headers.

' Create the html tag.
Dim xmlRoot As XmlElement = xmlDoc.CreateElement("html")
xmlDoc.AppendChild(xmlRoot)

' Create the head tag and append it under the html element.
Dim xmlHead As XmlElement = xmlDoc.CreateElement("head")
xmlRoot.AppendChild(xmlHead)

' Create the title tag, set it's text to "Database Table"
' and append it under the head element.
Dim xmlTitle As XmlElement = xmlDoc.CreateElement("title")
xmlTitle.AppendChild(xmlDoc.CreateTextNode("Database Table"))
xmlHead.AppendChild(xmlTitle)

Wow, that's a lot of code. What's going on there? First, let's look at the XmlDocument class. This is important when we're generating XML documents. It's what we use to create new elements. However, even though it creates new elements, it doesn't add them to the document. Thus, we need to use the AppendChild method of the appropriate element to add it to the document. As you can see above, we created a root element (html) and added that to the XML document (xmlDoc) first. Then we created a head element, and added that to the root element, not the xmlDoc. This was done in order to form a hierarchy, which is, in essence, what a XML (and by extension HTML) document is.

Here is what the resulting XML/XHTML document would look like so far:

<html>
  <head>
    <title>Database Table</title>
  </head>
</html>

So far so good, let's finish it off. Here's the rest of the code we'd need to make our simple HTML document:

' Create the body element and append it to the root.
Dim xmlBody As XmlElement = xmlDoc.CreateElement("body")
xmlRoot.AppendChild(xmlBody)

' Create the table and append it.
Dim xmlTable As XmlElement = xmlDoc.CreateElement("table")
xmlBody.AppendChild(xmlTable)

' Create the rows.
For Each row As DataRow In dataTable
  Dim xmlRow As XmlElement = xmlDoc.CreateElement("tr")
  xmlTable.AppendChild(xmlRow)

  ' Create the cells.
  For Each item As Object In row
    Dim content As String = ""
    If IsDBNull(item) = False Then content = CStr(item)
    Dim xmlCell As XmlElement = xmlDoc.createElement("td")
    xmlCell.AppendChild(xmlDoc.createTextNode(content))
    xmlRow.AppendChild(xmlCell)
  End For
End For

' Write the XML/HTML document.
Response.Write(xmlDoc.OuterXml)

And there you have it: a programmatic way to generate an HTML document. So why bother? Here's a few reasons:

Safety. If you generate your HTML document by concatenating strings, there's a chance you might forget to close a tag. If you generate the document programmatically, you can ensure that all your tags will always be closed.

Maintainability and readability. I've had to deal with code where the HTML is generated by concatenation. It's confusing and frustrating. If you generate your HTML documents programmatically, it's a lot easier for a future programmer to follow what's going on (especially if you, y'know, document it).

Reusability and modifiability. If you create your HTML document as a flat string, it makes it really hard to modify and reuse elsewhere in your code. For example, if you wanted to add a tag in the middle of your HTML document using the string concatenation method, you will have to do a lot of painful string manipulations. With the programmatic approach, it's as simple as just calling AppendChild on the appropriate XmlElement.

Using an XmlDocument to represent an XML document just makes sense. It's less crude and more versatile.