Kirk Evans Blog

.NET From a Markup Perspective

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

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

  • Comments 31

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.

  • Thanks for the tip , very useful
  • nice.
  • chacha,

    FYI,

    YOUR example works great, but I found some problems using xmlnamespaces with M$'s xmlnamespacemanager class. No errors, just no matches when I used a predicate. I got rid of the namespace prefixes in my xml and ditched the xmlnamespacemanager object and it worked great.
  • chacha,
    Care to post what the problem could have been? I have never had a problem using the XmlNamespaceManager class, and have used it many times. Instead of altering the source XML document, you might also consider using XPath statements such as:

    /*[local-name()='foo']/*[local-name()='bar]

    This would find the "bar" element in the following document:

    <foo xmlns="urn:xmladvice.com:examples">
    <bar>Here is your value</bar>
    </foo>
  • Kirk,

    In VB.NET I've managed to sucessfully create a 3 tier catagory system. Everything works great when your dealing with data at the same XML Node Level.

    ALTHOUGH ... HOW can I reference a 'Parent Node' Attribute (e.g. Level 2 Data) whilst within (e.g. Level 3 Data)

    Please can you help me fill in the missing blank ('*** ???CountryName??? ***') on line 17

    1 Sample with line numbers the other sample without line numbers

    START
    01) <%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="hdb_vb.WebForm1"%>
    02) <%@ Import Namespace="System.Xml" %>
    03) <HTML>
    04) <body>
    05) <form runat="server" ID="Form1">
    06) <h2>Hierarchical databinding test with XmlNode</h2>
    07) <asp:Repeater id="_rep1" runat="server">
    08) <itemTemplate>
    09) AAA:<%# (Ctype(Container.DataItem, System.Xml.XmlNode)).Attributes("WorldRegionName").Value %><br>
    10) <asp:Repeater runat="server" DataSource='<%# Container.DataItem %>' ID="Repeater1">
    11) <itemTemplate>
    12) &nbsp;&nbsp;Author:
    13) <%# (Ctype(Container.DataItem, System.Xml.XmlNode)).Attributes("CountryName").Value %>
    14) <br />
    15) <asp:Repeater runat="server" DataSource='<%# Container.DataItem %>' ID="Repeater2">
    16) <itemTemplate>
    17) &nbsp;&nbsp;&nbsp;&nbsp;<i><a href='<%# *** ???CountryName??? *** %>'><%# (Ctype(Container.DataItem, System.Xml.XmlNode)).Attributes("CountryMajorCityName").Value %></a></i><br />
    18) </itemTemplate>
    19) </asp:Repeater>
    20) </itemTemplate>
    21) </asp:Repeater>
    22) <hr />
    23) </itemTemplate>
    24) </asp:Repeater>
    25) </form>
    26) </body>
    27)</HTML>
    FINISH

    The same above except no line numbers ...


    <%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="hdb_vb.WebForm1"%>
    <%@ Import Namespace="System.Xml" %>
    <HTML>
    <body>
    <form runat="server" ID="Form1">
    <h2>Hierarchical databinding test with XmlNode</h2>
    <asp:Repeater id="_rep1" runat="server">
    <itemTemplate>
    AAA:<%# (Ctype(Container.DataItem, System.Xml.XmlNode)).Attributes("WorldRegionName").Value %><br>
    <asp:Repeater runat="server" DataSource='<%# Container.DataItem %>' ID="Repeater1">
    <itemTemplate>
    &nbsp;&nbsp;Author:
    <%# (Ctype(Container.DataItem, System.Xml.XmlNode)).Attributes("CountryName").Value %>
    <br />
    <asp:Repeater runat="server" DataSource='<%# Container.DataItem %>' ID="Repeater2">
    <itemTemplate>
    &nbsp;&nbsp;&nbsp;&nbsp;<i><a href='<%# *** ???CountryName??? *** %>'><%# (Ctype(Container.DataItem, System.Xml.XmlNode)).Attributes("CountryMajorCityName").Value %></a></i><br />
    </itemTemplate>
    </asp:Repeater>
    </itemTemplate>
    </asp:Repeater>
    <hr />
    </itemTemplate>
    </asp:Repeater>
    </form>
    </body>
    </HTML>


    Many Thanks In Advance...

    Regards

    Mark Dicken
  • Hi, Iam trying to do this with a Repeater control but it does'nt work, the next error is returned to me
    System.NullReferenceException: Object reference not set to an instance of an object.
    I dont't know wy Visual Studio Return this error, i put all the necesary references but it does'nt work.
    Can you help me please
  • Great Tip this i was looking for hours thank you
  • Hi,
    Like Hugo, I can't get the VB to work in my app:
    Object reference not set to an instance of an object.
    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

    Source Error:


    Line 23: <ItemTemplate>
    Line 24: <TR>
    Line 25: <TD><%# (CType(Container.DataItem, System.Xml.XmlNode))("tab").InnerText %></TD>
    Line 26: </TR>
    Line 27: </ItemTemplate>


    If I use CType(Container.DataItem, System.Xml.XmlNode)) the code compiles by my repeater is (understandably) empty.

    Can anyone help?

    Thanks

    Mark
  • Thanks for al the information. But I want to bind to a DropDownListbox. This seems to be very different, because a DropDownListbox doesn't have a DataItem to convert from...
    Does anyone have a clue (in VB perhaps...)

    Thank you!
  • PingBack from http://restaurants.247blogging.info/?p=621

Page 2 of 3 (31 items) 123
Leave a Comment
  • Please add 5 and 4 and type the answer here:
  • Post
Translate This Page
Search
Archive
Archives