Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

XML Processing using XSL with Parameters

4.11/5 (2 votes)
28 Mar 2012CPOL4 min read 29.6K  
Passing Parameters to XSL

Introduction

Recently, during the development of a consolidated report for a web application, we used XML/XSL processing to generate the report which is basically a custom grid generated out of the XSL processing. The screenshot of the user interface is given in the overview section.

The report was designed using a custom grid generated using the XSL from the XML data. The report was basically showing consolidated data for daily, MTD and yearly. The XML output contains data for daily, MTD and YTD for a given trade date. So the problem was extracting the corresponding data from the XML when the user selects Daily /MTD/Yearly in the UI.

As usual, the initial thoughts were to use three XSL for processing daily, monthly & yearly. But when looking forward, thoughts about maintainability and repetition of the code made me look for a more reliable solution. Let’s see how we implemented the solution.

Overview

Not going into the details of how the grid was developed; just adhering to the problem, let's look at the brief of the requirements.

To make the understanding much better, let's have a glance of the reporting screen. The user selects the report type (value will be either ‘D’,’Y’,’M’) from the screen and click the apply button; on the basis the user selection the XML data needs to be extracted and processed.

For example, in the report screen, the report header is one of the XML elements which needs to be extracted corresponding to the report type selected by the user. When the user selects ‘Daily’ from the report type, then XSL processor needs to extract the XPATHroot/reportparameters/reportdescription/description/@view’ = ‘D’ from the XML.

Image 1

XML Sample

Please find the sample XML below. The solution needs to extract the XML data from the nodes for attribute value like ‘view’ from ‘root/reportparameters/reportdescription/description/@view’ for report header corresponding to the report type.

The attributes have values like ‘D’, ‘M’, ‘Y’ which corresponds to daily, MTD, yearly respectively.

Similarly for the report data, this needs to be from ‘root/datarows/datarow/amounts/@aggregation’.

Image 2

Solution 1

The easiest solution is to have three XSL where the attribute value ‘D’,’M’,’Y’ is hard coded. But in the long run, this becomes a question for maintainability and the same code is repeated over the three XSL. The snippet of one of the three XSLs is given below. The XML/XSL processing technique is explained in solution 2.

XML
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
 
<div class="controlname reportdesc" style="font-style: italic">
<xsl:for-each select ="root/reportparameters/reportdescription">
<xsl:value-of select="description[@view='D']"/>
</xsl:for-each>
</div> 
 
<br/>
</xsl:template>
</xsl:stylesheet>

Solution 2

The best solution is to have a single XSL where parameter can be passed from web application which can be done from client side or server side depending on the requirement. The challenge will be how we can pass parameter to XSL from client side processing and whether the same can be done from server side too?

We will explain both the ways as we go.

Let’s quickly jump to the solution, not sure whether I have explained a lot rather than coming to the solution.

XML/XSL Processing from Client Side

The XSL processing is done by creating Microsoft.XMLDOM object to load the XML data. Similarly, object to load XSLT needs to be created from FreeThreadedDOMDocument. The transformation is done on the XSLT processor object created; this is done by calling the transform method on the above object.

The above process is preferred over the one where we can use "transformNode" method of Microsoft.XMLDOM object to process the XML since this one doesn’t allow two parameters in XSLT.

The steps involved are:

C#
1. var xml = new ActiveXObject("Microsoft.XMLDOM"); 
2. var xslt = new ActiveXObject("MSXML2.FreeThreadedDOMDocument");
3. xml.load("data.xml");
4. xslt.load("transformxsl.xsl");
5. var processor = new ActiveXObject("Msxml2.XSLTemplate");
6. processor.stylesheet = xslt;
7. var objXSLTProc = processor.createProcessor();
8. objXSLTProc.input = xml;
9. objXSLTProc.addParameter("reporttype", GetReportType());
10. objXSLTProc.transform();
11. document.getElementById("divReportGrid").innerHTML = objXSLTProc.output;

In the above code, line # 3 does the loading of the XML; this can also be done by using a call to a separate ASPX page where response type is ‘text/xml’.

Line # 9 does the actual parameter passing; the objXSLTProc object is defined with a parameter name ‘reporttype’. The value of the same is retrieved using the JavaScript function GetReportType().

Finally, the report is rendered using the XSL processor output to a DIV tag.

Let’s Have a Look at the XSL (For Explanation, It’s a Sample from the Original XML)

XML
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:param name ="reporttype"></xsl:param>

<xsl:template match="/">
<div class="controlname reportdesc" style="font-style: italic">
<xsl:for-each select ="root/reportparameters/reportdescription">
<xsl:value-of select="description[@view=$reporttype]"/>
</xsl:for-each>
</div> 
<br/>
</xsl:template>
</xsl:stylesheet>

In the above XSL, a XSL param named ‘reporttype’ is defined. And the report header is processed using the XPATH for the attribute ‘view’ which is linked to the XSL param defined.

XML/XSL Processing from Server Side (C#)

The XML/XSL processing is done using the XPathDocument and applying parameter on the XsltArgumentList object. Finally, the same is transformed on the XPathDocument object using the XslCompiledTransform object. After XSL processing, the HTML output will be in the StringWriter object.

C#
MemoryStream ms = 
   new MemoryStream(System.Text.Encoding.UTF8.GetBytes(//Get the XML for processing));
XPathDocument document = new XPathDocument(ms);
XslCompiledTransform transform = new XslCompiledTransform();
transform.Load(Server.MapPath(@"/XSL/Sample.xsl"));
StringWriter sw = new StringWriter();
XsltArgumentList xslArg = new XsltArgumentList();
xslArg.AddParam("reporttype", "", reportTypeParam.ToString());

transform.Transform(document, xslArg, sw);

Solution Implementation

Finally, the solution applied was client side XSL processing using a single XSL. The server side XML/XSL processing was applied for generating an Excel report.

Summary

In the article, I tried to explain various ways by which XML/XSL processing with parameter passing can be done and applied to various applications.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)