Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Cascade XSL

0.00/5 (No votes)
29 Dec 2004 1  
An engine that transforms XML files on a web server.

Introduction

Layout A Layout B

The major advantage of using XSL is the ease with which you can create and/or update a page layout. In the included demo project, replace the file 'DirTransform.xsl.aspx' by the 'DirTransform.xsl.aspx' and you have a completely new layout!

The ASP.NET uses 'user controls' for adding consistency to a web site. Version 2.0 of ASP.NET introduces master-content pages which is yet another way for creating a template driven site. C-XSL provides an alternative way, where the documents of a website are XML files and contain only the content. The layout of the site is placed in a separate XSL file.

Using the Code

This article apart from C-XSL, it presents the use of Filters and Modules. The project consists of three parts, cxslModule, cxslFilter, and cxslProcessor.

cxslModule

To install the module, we put the following code in the <configuration>/<system.web> section of Web.config file.

<httpModules>
        <add name="CXSL::cxslModule" type="CXSL.cxslModule, cxsl" />
</httpModules>

The Module registers two event handlers using the following code:

public void Init(HttpApplication application)
{
    application.BeginRequest +=
       (new EventHandler(this.Application_BeginRequest));
    application.PostRequestHandlerExecute +=
       new EventHandler(this.Aplication_PostRequestHandlerExecute);
    return;
}

The BeginRequest event occurs when ASP.NET receives a request. Here, we check if the user requests an *.xml.aspx, and if so, we add the filter which buffers the response.

private void Application_BeginRequest(Object source, EventArgs e)
{
    HttpApplication application = (HttpApplication)source;
    HttpContext context = application.Context;
    if(IsXMLfile(context.Request.FilePath))
    {
        context.Response.Filter = new cxslFilter(context.Response.Filter);
        context.Response.Buffer= true;
    }
    return;
}

The PostRequestHandlerExecute event occurs when the request is finished and the response has been send to the client. At the time PostRequestHandlerExecute occurs, the Response object has already sent the result to the client and the Response.Output is clear. That's why we need the filter, so we can buffer the output, and prevent it from reading the client.

If the request was for an *.xml.aspx file, we use the filter to retrieve the result of the page, and use the cxslProcessor class to do the transformation. Finally, we remove the filter and return the result to the client.

private void Aplication_PostRequestHandlerExecute(Object source,
                                                          EventArgs e)
{
    HttpApplication application = (HttpApplication)source;
    HttpContext context = application.Context;

    if(IsXMLfile(context.Request.FilePath))
    {
        //get the buffered output and remove the filter
        String output="";
        context.Response.Clear();

        cxslFilter cFilter=(cxslFilter)context.Response.Filter;
        output=cFilter.GetBuffer();
        context.Response.Filter = cFilter._sink;

        // cascade and return the result
        cxslProcessor cxslProc= new cxslProcessor(application);
        output = cxslProc.fn_Proccess(output);
        context.Response.Write(output);
    }
    return;
}

cxslFilter

A filter receives the results of a request, processes them, and then sends them to the next filter. The last filter in the chain sends the result to the client. A typical use of a filter is to make uppercase the word of a company, censor bad words, etc. Here, we use a filter in an odd way. It keeps everything it receives in a buffer and sends nothing to the next filter.

The next piece of code caches the input of the filter in the string _outstr.

public override void Write(byte[] buffer, int offset, int count)
{
    // cache the output into _outstr
    System.Text.Encoding Enc=System.Text.Encoding.Default;
    _outstr += Enc.GetString(buffer,offset,count);
}

cxslProcessor

The following diagram presents the logic of C-XSL.

C-XSL - Flow

The process is initialized for every request of pages ending in .xml.aspx. The output of the page might be transformed using the corresponding .xsl.aspx file, if it exists. Then, it merges the output with the result of General.xml.aspx which also might be transformed by General.xsl.aspx. Finally, the result can be transformed by DirTranform.xsl.aspx. That is repeated for every parent directory till it reaches the application root.

Installing and Using the Demo Project

Unzip the files inside your /wwwroot/ directory. You should now have a directory called /wwwroot/Demo/. Alternatively, you may create a virtual directory in your IIS server named 'Demo' that points to the unzipped files. Open the IIS configuration console, left-click on '/Demo/' and select Properties. Select the tab 'Directories', and on the 'Applications Settings', click Create. You have now created an application. Try accessing the project by visiting 'http://yourserver/Demo/Home/Default.xml.aspx'.

The demo site has four sections where sections 2-3 has two or more subsections. Check out '/Section2/General.xml.aspx' to see how you can generate XML programmatically or through a database.

The file 'DirTransform.xsl.aspx' is the XSL file that transforms the content of the site into HTML. Play around with it or replace it with 'DirTransform.xsl.aspx' to see the result.

Points of Interest

One problem I had to solve was how to merge two XML documents since an XML document must have only one root element. The solution was to put both inside a <LevelContext> element.

Once I started using this system, it became clear that there is no need to do transformations at every level. It's simpler to use a single DirTransform.xsl.aspx at the root to do all the transformations.

The way cxslFilter works is not perfect and causes problems with page caching and Viewstate validation. I am still working on it!

History

  • C-XSL version 1.0

    This code is about a year old. I have used it on a couple of sites. If you like the ideas presented here, you could also take a look at nkCMS: the successor of C-XSL combined with a CMS system.

Related Articles

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.

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