Click here to Skip to main content
Click here to Skip to main content

Generate dynamic ASP.NET pages by using XML and XSLT

By , 15 Oct 2004
 

Introduction

Sometimes you need to create dynamic pages. You may allow users to build their own applications by selecting the fields they need. In this article, I will show how to build dynamic applications by using ASP.NET and XML. In this example, I use XML for meta-programming or generative programming. I use XML with an XSLT to generate ASP.NET PRE, utilizing intrinsic ASP.NET parsing methods with the XSLT output. Steps that we need to do:

  • Create XML file (schema of our page).
  • Create an XSLT style to transform XML into ASP.NET PRE.
  • Transform XML, and create server controls defined by the generated ASP.NET PRE at runtime.
  • Insert the instantiated controls into the page's control collection.
  • Handle postback events from server controls.

First, what we need to come up with is a good structure of our page in a XML file. A basic page structure is defined below. The example structure consists of field elements, with attributes, properties and listitems.

<FORM>
  <PAGES>
    <PAGE title="Page Title" id="page_1">
      <FIELDS>
        
    <!-- create regular TextBox -->
    <FIELD type="TextBox" label="Last Name:" required="true">
          <PROPERTIES>
            <PROPERTY name="ID">LAST_NAME</PROPERTY>
          </PROPERTIES>
        </FIELD>

    <!-- create multiline TextBox (textarea) -->
        <FIELD type="TextBox" label="Description:">
          <PROPERTIES>
            <PROPERTY name="ID">DESCRIPTION</PROPERTY>
            <PROPERTY name="TextMode">MultiLine</PROPERTY>
            <PROPERTY name="Cols">30</PROPERTY>
            <PROPERTY name="Rows">2</PROPERTY>
          </PROPERTIES>
        </FIELD>

    <!-- regular textbox prefilled with text -->
    <FIELD type="TextBox" label="Prefilled Contrl:">
          <PROPERTIES>
            <PROPERTY name="ID">PREFILLED_CONTROL</PROPERTY>
            <PROPERTY name="Text">Some Text</PROPERTY>
          </PROPERTIES>
        </FIELD>

        <!-- regular text box which must filled 
                                 and allowed Date datata type -->
        <FIELD type="TextBox" label="Start Date:" 
                      required="true" validation="Date">
          <PROPERTIES>
            <PROPERTY name="ID">START_DATE</PROPERTY>
          </PROPERTIES>
        </FIELD>

    <!-- create select box -->
        <FIELD type="DropDownList" label="Title:">
          <PROPERTIES>
            <PROPERTY name="ID">TITLE</PROPERTY>
          </PROPERTIES>
          <LISTITEMS>
            <LISTITEM value="">Select One</LISTITEM>
            <LISTITEM value="1">Architector</LISTITEM>
            <LISTITEM value="2">Sr. Developer</LISTITEM>
            <LISTITEM value="3">Programmer</LISTITEM>
            <LISTITEM value="4">Web Designer</LISTITEM>
          </LISTITEMS>
        </FIELD>

    <!-- radio buttons list -->    
        <FIELD type="RadioButtonList" label="Are you US citizen?">
          <PROPERTIES>
            <PROPERTY name="ID">IS_US_CITIZEN</PROPERTY>
            <PROPERTY name="RepeatColumns">1</PROPERTY>
            <PROPERTY name="RepeatDirection">Vertical</PROPERTY>
            <PROPERTY name="RepeatLayout">Table</PROPERTY>
            <PROPERTY name="TextAlign">Right</PROPERTY>
          </PROPERTIES>
          <LISTITEMS>
            <LISTITEM value="1">Yes</LISTITEM>
            <LISTITEM value="0">No</LISTITEM>
          </LISTITEMS>
        </FIELD>

    <!-- check box list -->
        <FIELD type="CheckBoxList" label="Languages:">
          <PROPERTIES>
            <PROPERTY name="ID">LANGUAGES</PROPERTY>
            <PROPERTY name="RepeatColumns">1</PROPERTY>
            <PROPERTY name="RepeatDirection">Vertical</PROPERTY>
            <PROPERTY name="RepeatLayout">Table</PROPERTY>
            <PROPERTY name="TextAlign">Right</PROPERTY>
          </PROPERTIES>
          <LISTITEMS>
            <LISTITEM value="C#">C#</LISTITEM>
            <LISTITEM value="Java">Java</LISTITEM>
            <LISTITEM value="VB">Visual Basic</LISTITEM>
          </LISTITEMS>
        </FIELD>

    <!-- here is a hyperlink (a) -->
        <FIELD type="HyperLink">
          <PROPERTIES>
            <PROPERTY name="ID">LINK</PROPERTY>
            <PROPERTY name="NavigateUrl">javascript:void(alert('Hello ooo'));
            </PROPERTY>
            <PROPERTY name="Text">Say Hello</PROPERTY>
          </PROPERTIES>
        </FIELD>

    <FIELD type="html" src="file path"/>

    <!-- you can place here any other asp controls -->

      </FIELDS>
    </PAGE>
    
    ...

  </PAGES>
</FORM>

Next step is to create XSLT style to transform our XML schema The XSLT iterates through each field, first outputting a label for the field as plain text. The stylesheet also checks if the field is required, and adds a RequiredFieldValidator if needed. The stylesheet then creates a Web Control (it could be any valid web control such as TextBox, RadioButtonList, DropDownList, etc.). ListItems are created for each of the ListControls.

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:asp="remove">
  <xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml-declaration="yes">
  </xsl:output>
  <xsl:template match="/">

   <!-- page id parameter if we have more than 1 page in our XML file -->
   <xsl:param name="pageid"/>

     <!-- start form page -->
     <table cellpadding="0" cellspacing="5">

       <!-- set title of the current page -->
       <tr>
        <td colspan="3" align="center" style="font-size:25px">
         <xsl:value-of select="FORM/PAGES/PAGE[@id=$pageid]/@title" />
        </td>
       </tr>
       <tr><td colspan="3" style="height:20px"></td></tr>

       <!-- iterate through page fields -->
       <xsl:for-each select="FORM/PAGES/PAGE[@id=$pageid]/FIELDS/FIELD">

       <!-- create row -->
       <xsl:element name="tr">
        <xsl:attribute name="id">
          TR_<xsl:value-of select="PROPERTIES/PROPERTY[@name='ID']"></xsl:value-of>
        </xsl:attribute>

        <!-- hide the row -->
        <xsl:if test="@display='none'">
         <xsl:attribute name="style">display:none;</xsl:attribute>
        </xsl:if>

        <xsl:choose>

         <!-- this is the way to place "include" files into your PRE -->
         <xsl:when test="@type='HTML'">
          <td colspan="3">
            <!-- #include file="<xsl:value-of select="@src"></xsl:value-of>" -->
          </td>
         </xsl:when>

         <!-- other controls -->
         <xsl:otherwise>

         <!-- field label column -->
         <td valign="top">
          <xsl:value-of select="@label" />
         </td>

         <!-- field column -->
         <td>

          <!-- field element -->
          <xsl:element name="asp:{@type}">
           <xsl:attribute name="runat">server</xsl:attribute>
           <xsl:for-each select="./PROPERTIES/PROPERTY">
             <xsl:attribute name="{@name}">
               <xsl:value-of select="current()"></xsl:value-of>
             </xsl:attribute>
           </xsl:for-each>
           <xsl:for-each select="./LISTITEMS/LISTITEM">
            <asp:ListItem value="{@value}">
              <xsl:value-of select="current()"></xsl:value-of>
            </asp:ListItem>
           </xsl:for-each>
          </xsl:element>
         </td>

         <!-- validation message column -->
         <td>
          <xsl:if test="@required='true'">
           <asp:RequiredFieldValidator ErrorMessage="Required" runat="server" 
                 ControlToValidate="{PROPERTIES/PROPERTY[@name='ID']}" />
          </xsl:if>

          <xsl:if test="@validation='Date'">
           <asp:CompareValidator ErrorMessage="Dates Only" runat="server" 
                Operator="DataTypeCheck" Type="Date" 
                ControlToValidate="{PROPERTIES/PROPERTY[@name='ID']}" />
          </xsl:if>

          <xsl:if test="@validation='Number'"> 
           <asp:CompareValidator ErrorMessage="Numbers Only" runat="server" 
               Operator="DataTypeCheck" Type="Integer" 
               ControlToValidate="{PROPERTIES/PROPERTY[@name='ID']}" />
          </xsl:if>

          <xsl:if test="@validation='Currency'">
           <asp:CompareValidator ErrorMessage="Currency Only" runat="server" 
               Operator="DataTypeCheck" Type="Currency" 
               ControlToValidate="{PROPERTIES/PROPERTY[@name='ID']}" />
          </xsl:if>
         </td>
        </xsl:otherwise>

       </xsl:choose>
      </xsl:element>

      </xsl:for-each>
     </table>
  </xsl:template>
</xsl:stylesheet>

Our XSLT file has a prefix (xmlns:asp="remove") defined for the XSL namespace. This is used to generate plain HTML. Now we are ready to write our Page transformer.

    ...
    private readonly string XslFile = @"...\default.xslt";
    private readonly string XmlFile = @"...\default.config";

    ...
    private void Page_Load(object sender, System.EventArgs e)
    {
        string pageId = "page_1";

        if (!Page.IsPostBack)
        {

            /**
             * Transform aspx page with fields from xml file
             * Get transform result as a string
             * Parse controls into a parent control holder
             */

            XmlDocument xdoc = new XmlDocument();
            xdoc.Load(XmlFile);

            // load xslt to do transformation
            XslTransform xsl = new XslTransform();
            xsl.Load(XslFile);

            // load xslt arguments to load specific page from xml file
            // this can be used if you have multiple pages
            // in your xml file and you loading them one at a time
            XsltArgumentList xslarg = new XsltArgumentList();
            xslarg.AddParam("pageid", "", pageId);

            // get transformed results
            StringWriter sw = new StringWriter();
            xsl.Transform(xdoc, xslarg, sw);
            string result = sw.ToString().Replace("xmlns:asp=\"remove\"", 
                     "").Replace("&lt;","<").Replace("&gt;",">");
            // free up the memory of objects that are not used anymore
            sw.Close();

            // parse the controls and add it to the page
            Control ctrl = Page.ParseControl(result);
            Page.Controls.Add(ctrl);
        }
    }

    private void BtnSave_Click(object sender, System.EventArgs e)
    {
        // save data into a data container
        // ...
        Response.Write (Request.Form["LAST_NAME"]);
    }

Conclusion

In this article, we separate data from content to make a cleaner design and for better maintainability. When XML is combined with XSLT, ASP.NET server controls become even more powerful. This opens up numerous possibilities for dynamic and robust systems.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

rafael_p
Web Developer
United States United States
Member
I am Microsoft Certified in .NET
I have over seven-year experience with client-server application development (full project lifecycle) on Windows platforms.
I've focused on creating middle tier, web application development, GUI development, custom data management software, and database programming.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralI am still waiting for DLLmemberPrashant Trambake28 Aug '12 - 22:34 
I am still waiting for DLL... :(
GeneralMy vote of 2memberLOKIN SHAH1 Aug '12 - 0:42 
So many replies, but no response for working example
Questionmissing dllmemberhasanMousavi9 May '12 - 18:06 
i cannot find the dll files below :
using WTMI.Util;
using WTMI.Collections;

QuestionGetting error on ReflectionManagermembersatishkulala99922 Feb '12 - 19:13 
References missing for "ReflectionManager". Unable to run the build. Please let me know if you any information on this. Thanks in advance
QuestionWTMI is not a component of .Netmemberadeel198110 Feb '12 - 20:13 
I found WTMI as an assembly of Java Frown | :( br /> 
Always believe in God and never let misfortunes make you give up
QuestionThe code is not workingmemberadeel19818 Feb '12 - 20:40 
First of all WTMI is not recognised by the CLR.I am using .Net 2.0 and ObjectEntryCollection is also not recognised.It is an object of Java.Kindly help me asap.Thanks
 
Always believe in God and never let misfortunes make you give up
QuestionDynamic HTML Code generatormemberJohn Shaening7 Feb '12 - 8:04 
I was impressed by the code you have provided.
 
I need someone to develop something similar to be used in a cloud based environment (Azure using MVC). Would you be available for any contract work. If so please let me know.
John Shaening

QuestionCan you provide this code for Visual Studio 2010 version?membernandukjadhav24 Nov '11 - 0:21 
Hi,
 
Thanks for your amazing work!!!
 
Can you provide me same code for visual studio 2010 version?
 
Please help me on that.
 
Thanks,
Nandy.
QuestionCreate dynamic template asp.net page using c#memberFarhad sharifi20 Oct '11 - 17:43 
I'm going to create a dynamic template with asp.net using c#.
the template page is consist of three separate parts.
first main menu which is located at the top bar.
second sub menu which is located at the left side bar.
and third part is right side of the page which is show the details.
the process is: if you click on the any of the main menu the left side bar should refresh only not all the page and show all the sub-menu. then once you choose any of the sub-menu the right side should only refresh and show the details of the sub-menu.
the main point is i don't want to refresh all page by each menu selection.
could you please guide me for this template.
appreciate your consideration.
 
Best Regards,
FS
Questionsend me a version with WTMI codememberMember 189751017 Oct '11 - 6:40 
My email: jfbinaghi@gmail.com

Could anybody send me a version with WTMI code ?

Thanks
AnswerRe: send me a version with WTMI codememberjrroy3 Feb '12 - 3:23 
Where can I download the WTMI code?
Can someone send me a copy at jrroy@devteach.com?
GeneralMy vote of 4memberDinesh Uthayakumar16 Jun '11 - 2:11 
Flexible and extensible approach
Generalmissing dll files WTMI.Util, WTMI.CollectionsmemberAmy.8412 Apr '11 - 4:14 
Hello,
 
i cannot find the dll files below :
using WTMI.Util;
using WTMI.Collections;
 
and as i see, many have asked the same question..
did any one get a reply ? Frown | :(
 
hope you can help !
Thanks
GeneralRe: missing dll files WTMI.Util, WTMI.CollectionsmemberMashudu Nemukula25 Apr '11 - 2:29 
If you managed to get the WTMI.Util could you please help me with it and send it to mnemukula@gmail.com?
 
many thanks,
Mashudu Nemukula
Software Engineer
Korbitec Pty(Ltd)

QuestionCan someone send me the WTMI code???memberMario Patricio25 Mar '11 - 8:34 
Please, send me, if possible, the WTMI code.
 
focus_man1@hotmail.com
 
Thanks
GeneralWorking examplememberanarych115 Dec '10 - 4:21 
try changing xslt like this :
<xsl:param name="pageid">page_1</xsl:param>
 
For me worked....
 
But I have another problem. Form disappears after submitting...
GeneralRe: Working examplememberMember 171756416 Dec '10 - 4:44 
Hi,
I did this change but now Error "Unknown server tag 'asp:html'."
Please let me know that how I can remove this
 
Regards
Basharat
GeneralWorking examplememberMember 171756416 Dec '10 - 4:48 
You can see the form on your web page if you have bind this string to and cotrol on you page
e.g
Control tr = Page.ParseControl(result);
this.thisDiv.Controls.Clear(); // thisDiv is the dive on you page with run at server
this.thisDiv.Controls.Add(tr);
 
Regards
Basharat
Questionplease send me a working version (with WTMI)memberdong yue wang9 Nov '10 - 23:57 
My email: dongyue.wang@hotmail.fr
 
Could anybody send me a version with WTMI code Smile | :) ?
 
Thanks
GeneralPlease send the working versionmemberLightBook5 Nov '10 - 7:21 
please send the working version to lightbook123@gmail.com
GeneralMy vote of 5membershijitha7 Sep '10 - 1:11 
Awesome Brainy Deal... Thanks
GeneralNeed a runnable versionmemberTaschi23 Aug '10 - 9:00 
HI! Could anyone please explain me how to run this sample code?
No project file is included?
 
Sorry for this weird question!
GeneralMy vote of 1memberlibniz16 Aug '10 - 19:33 
can't run
QuestionHow to show hide controls based on the status of other controlmemberMember 346300330 Jun '10 - 6:59 
Hi,
How can I show or hide controls based on the state of other controls. E.g. based on the value selected from the drop-down list I will need to show additional drop-down list which were not visible earlier.
Is this functionality possible?
 
Thanks in advance for your help.
AnswerRe: How to show hide controls based on the status of other controlmembershijitha7 Sep '10 - 1:15 
hi you can use the jqueary ajax postback as that wont load the whole page but it ll load only the what we need... I used as the same instead of postback to the Page better we can do that in handler. ll be having very good effect.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 15 Oct 2004
Article Copyright 2004 by rafael_p
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid