Introduction
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))
{
String output="";
context.Response.Clear();
cxslFilter cFilter=(cxslFilter)context.Response.Filter;
output=cFilter.GetBuffer();
context.Response.Filter = cFilter._sink;
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)
{
System.Text.Encoding Enc=System.Text.Encoding.Default;
_outstr += Enc.GetString(buffer,offset,count);
}
cxslProcessor
The following diagram presents the logic of C-XSL.
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
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.