Kirk Evans Blog

.NET From a Markup Perspective

Use ASP.NET Data Binding to Bind Directly to XML (sans DataSet)

As I mentioned in my previous blog post about binding, any object that supports IEnumerable can be used as the DataSource for data binding in ASP.NET.  If you are processing XML, the XmlDocument class does not support IEnumerable (after all, it is a tree, not a list).  You can, however, bind to a set of nodes within an XML document, and use ASP.NET data binding to navigate through the rest of the document.

Suppose we have the XML document:

<Projects iProjectID =”13 vProjectName =”Plumber’s Project >
<Packages iPackageID =”36 vPackageName =”Bowser >
<Modules iModuleID =”76 vModuleName =”Bob-omb Module />
</Packages>
<Packages iPackageID =”40 vPackageName =”Princess >
<Modules/>
</Packages>
</Projects>

We can select a set of nodes (called a node list) using XPath statements and the SelectNodes method of the XmlNode class. XmlNode.SelectNodes returns an object called an XmlNodeList, and this object is a collection that supports IEnumerable.  XmlNodeList, then, can be used as the DataSource for an ASP.NET data bound control.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml;

namespace ExampleWeb
{
  public class DataBindtoNodeSet : System.Web.UI.Page
  {
    protected System.Web.UI.WebControls.DataList DataList1;
  
    private void Page_Load(object sender, System.EventArgs e)
    {
      XmlDocument doc = new XmlDocument();
      doc.Load(Server.MapPath(“data/xmlfile1.xml”));
      XmlNodeList nodes = doc.SelectNodes(“Projects/Packages”);
      
      DataList1.DataSource = nodes;
      DataList1.DataBind();
    }

    #region Web Form Designer generated code
    override protected void OnInit(EventArgs e)
    {
      InitializeComponent();
      base.OnInit(e);
    }
    
    private void InitializeComponent()
    {
      this.Load += new System.EventHandler(this.Page_Load);

    }
    #endregion

  }
}

You can see that the code-behind is really simply, the work is done in the Page_Load event.  We use the SelectNodes method to retrieve an XmlNodeList, and use that as the DataSource for our ASP.NET DataList control.

Here is the .aspx view of the code.

<%@ Page language=”c#” Codebehind=”DataBindtoNodeSet.aspx.cs” AutoEventWireup=”false” Inherits=”ExampleWeb.DataBindtoNodeSet” %>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN” >
<HTML>
  <HEAD>
    <title>DataBindtoNodeSet</title>
    <meta name=”GENERATOR” Content=”Microsoft Visual Studio .NET 7.1″>
    <meta name=”CODE_LANGUAGE” Content=”C#”>
    <meta name=”vs_defaultClientScript” content=”JavaScript”>
    <meta name=”vs_targetSchema” content=”http://schemas.microsoft.com/intellisense/ie5″>
  </HEAD>
  <body MS_POSITIONING=”GridLayout”>
    <form id=”Form1″ method=”post” runat=”server”>
      <asp:DataList id=”DataList1″ style=”Z-INDEX: 101; LEFT: 256px; POSITION: absolute; TOP: 144px”
        runat=”server”>
        <ItemTemplate>
          <h1><%# ((System.Xml.XmlNode)Container.DataItem).Attributes[“iPackageID”].Value %></h1>
        </ItemTemplate>
        </asp:DataList>
    </form>
  </body>
</HTML>

The real work here is done in the ItemTemplate, specifically where we use the special binding syntax (<%# … %>) for ASP.NET.  The Container.DataItem property is pointing at the current thing in the IEnumerable object being bound to.  XmlNodeList is a collection of XmlNode references, so Container.DataItem will point to a single XmlNode object reference.  So, we cast Container.DataItem to an XmlNode type, after which we can access the DOM methods of the XmlNode object.  In this example, we use the Attributes collection.