Now that we have had an overview of all the important classes and interfaces, let us kick off our demonstration by considering an example that leverages the classes found in the System.Xml.Xsl namespace. We will split the implementation into the following three sections, with each section building on the functionality of the previous section.
- Transforming and displaying data using XslTransform class
- Adding paging capability to the output
- Customizing the output of the displayed records using XSLT Extensions
We will start off by looking at the first part.
How to transform XML data using XslTransform class
As we already know, the XslTransform class exists in the System.Xml.Xsl namespace. We can use this class to transform XML data from any store as long as the data store implements the IXPathNavigable interface. Since the XslTransform class works based on a streaming base model, it is also possible to combine several transforms together. This capability allows us to design powerful and flexible applications. An XSL stylesheet that needs to be transformed using the XslTransform class must have the following namespace declaration included as part of its xsl:stylesheet declaration.
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
Before we take a look at the code sample, let us have a brief look at the methods of the XslTransform class that we will be using in this article.
- Load - This method has several overloads and it provides for loading of an XSL stylesheet into an XslTransform object from any one of the following resources: a string that specifies the URL, from an XmlReader object, or from an XPathNavigator object, and so on.
- Transform - Allows us to transform the XML data into a specified format using the stylesheet that is already loaded.
For this example, we will create a simple Web form that displays all the records in the Products table of the Northwind database using an XSLT stylesheet. For this reason, let us create a new ASP.NET Web application named CustomPagingXSL using Visual C#. Once the project is created, add a new ASP.NET Web form named XslTransformExample1.aspx to the project.
In the Page_Load event of the Web form, add the following lines of code.
private void Page_Load(object
sender, System.EventArgs e)
{
//Retrieve the connection string from the Web.config file
string
connString =
System.Configuration.ConfigurationSettings.AppSettings["connectionString"];
SqlConnection
sqlConn = new SqlConnection(connString);
//Open the connection to the database
sqlConn.Open();
//Instantiate the SqlCommand object and pass the query to
be executed
SqlCommand sqlCommand = new SqlCommand("Select * from Products for xml
auto,elements",sqlConn);
//Execute the query
XmlReader
reader = sqlCommand.ExecuteXmlReader();
//Associate the XmlReader object with the XPathDocument
object
XPathDocument
xpathDoc = new XPathDocument(reader);
//Close the connection to the database
sqlConn.Close();
XslTransform
transform = new XslTransform();
//Load the XSL stylsheet into the XslTransform object
transform.Load(Server.MapPath("xmlpaging.xsl"));
//Invoke the transform method
transform.Transform(xpathDoc,null,Response.Output);
}
In the above lines of code, we retrieve the data (in the form of XML) from the products table and then apply an external XSLT stylesheet (named xmlpaging1.xsl) on the XML data to emit HTML. Let us walk through the above code.
We start by retrieving the connection string from the Web.config file. The Web.config file contains the following entry to store the connection string.
<appSettings>
<add
key="connectionString"
value="server=localhost;database=northwind;uid=sa;pwd=thiru;">
</add>
</appSettings>
Once the connection string is retrieved into a local variable, we then pass it to the constructor of the SqlConnection object. Then we open the connection by invoking the Open method of the SqlConnection object.
SqlConnection sqlConn = new
SqlConnection(connString);
//Open the connection to the database
sqlConn.Open();
Here we create an instance of the SqlCommand object passing in the SQL command to be executed and the SqlConnection object as arguments. As you can see from the code, we use the FOR XML clause in the SQL query to retrieve XML data directly from the database.
//Instantiate the SqlCommand object and
pass the query to be executed
SqlCommand sqlCommand = new SqlCommand("Select
* from Products for xml auto,elements",sqlConn);
Then we execute the SQL query by invoking the ExecuteXmlReader method of the SqlCommand object and assign the returned XML stream to an XmlReader object.
//Execute the query
XmlReader reader =
sqlCommand.ExecuteXmlReader();
Now we load the XML data into an XPathDocument object by passing in the XmlReader object to the constructor of the XPathDocument object.
//Associate the XmlReader object with the
XPathDocument object
XPathDocument xpathDoc = new
XPathDocument(reader);
//Close the connection to the database
sqlConn.Close();
Here we create an instance of the XslTransform object and then load the XSL stylesheet into an XslTransform object by invoking the Load method of the XslTransform object.
XslTransform transform = new
XslTransform();
//Load the XSL stylsheet into the XslTransform
object
transform.Load(Server.MapPath("xmlpaging.xsl"));
Finally we transform the XML data to HTML by invoking the Transform method of the XslTransform object passing in the previously created XPathDocument and the Response.Output object as arguments.
//Invoke the transform method
transform.Transform(xpathDoc,null,Response.Output);
Now that we have had a look at the code that carries out the transformation, let us take a look at the
code of the XSLT stylesheet xmlpaging1.xsl.
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE> XSLT In .NET </TITLE>
</HEAD>
<BODY>
<span
align="center" style="color:Blue;background-color:White;font-
weight:bold;height:25px;width:634px;Z-INDEX: 102; LEFT: 203px;
POSITION: absolute; TOP:
69px"> This is a sample Application to illustrate Paging in .NET
</span>
<table style="Z-INDEX:
101; LEFT: 171px; WIDTH: 501px; POSITION:
absolute; TOP: 125px; HEIGHT:
322px" border="1" cellSpacing="1"
cellPadding="1">
<center>
<xsl:for-each
select="//Products">
<xsl:element
name="tr">
<xsl:element
name="td">
<xsl:value-of
select="ProductID" />
</xsl:element>
<xsl:element
name="td">
<xsl:value-of
select="ProductName" />
</xsl:element>
<xsl:element
name="td">
<xsl:attribute
name="align">center</xsl:attribute>
<xsl:value-of
select="SupplierID" />
</xsl:element>
<xsl:element
name="td">
<xsl:attribute
name="align">center</xsl:attribute>
<xsl:value-of
select="CategoryID" />
</xsl:element>
<xsl:element
name="td">
<xsl:attribute
name="align">center</xsl:attribute>
<xsl:value-of
select="QuantityPerUnit" />
</xsl:element>
</xsl:element>
</xsl:for-each>
</center>
</table>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
In the XSL stylesheet, we declare a TABLE element and then inside the table element, we use an xsl:for-each construct to loop through all the elements present in the XML data and display each element in its own table row. Inside the table's TD element, we display the actual values from the XML data by using the xsl:value-of element. The output produced by the above code looks like the following.
The above output shows all the records in the Products table in a single page since we did not have the code required to provide paging mechanism. In the next section, we will see how to declare parameters in an XSL stylesheet and then supply values to it at runtime.
Declaring parameters in an XSL stylesheet and supplying values to those Parameters
To implement paging for the above situation, we need to be able to pass parameters to the stylesheet, and these parameters can be used to specify information such as the number of records to be displayed, the page number to be displayed, as well as the total number of records. Accomplishing this requires the following two steps.
- Declaring parameters in the XSL stylesheet
- Supplying parameters to the stylesheet
For this example, let us create a new XSL stylesheet named xmpaging2.xsl and the code for the XSL stylesheet looks like the following.
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />
<!--Set the paging characteristics - number of
records per page and the page number and record count-->
<!-- Set the number of records per page-->
<xsl:variable name="recordsPerPage"
select="77" />
<!-- Page Number field -->
<xsl:variable name="pageNumber"
select="0" />
<!--Record Count Field-->
<xsl:variable name="recordCount"
select="77" />
<xsl:template match="/">
<HTML>
<HEAD>
<TITLE> XSLT In .NET </TITLE>
</HEAD>
<BODY>
<span align="center"
style="color:Blue;background-color:White;font-weight:bold;height:25px;width:634px;Z-INDEX:
102; LEFT: 203px; POSITION: absolute; TOP: 69px"> This is a sample
Application to illustrate XSLT in .NET
</span>
<table style="Z-INDEX: 101; LEFT: 171px; WIDTH:
501px; POSITION: absolute; TOP: 125px; HEIGHT: 322px" border="1"
cellSpacing="1" cellPadding="1">
<center>
<xsl:for-each
select="//Products">
<!--this performs the
output in table format - and shows only that many records specified in the
recordcount variable -->
<xsl:if
test="position() > $recordsPerPage * number($pageNumber) and position()
<= number($recordsPerPage * number($pageNumber) +
$recordsPerPage)">
<!--
Each record on a seperate row -->
<xsl:element name="tr">
<xsl:element
name="td"> <xsl:value-of
select="ProductID" />
</xsl:element>
<xsl:element
name="td">
<xsl:value-of
select="ProductName" />
</xsl:element>
<xsl:element
name="td">
<xsl:attribute
name="align">center</xsl:attribute>
<xsl:value-of
select="SupplierID" />
</xsl:element>
<xsl:element
name="td">
<xsl:attribute
name="align">center</xsl:attribute>
<xsl:value-of
select="CategoryID" />
</xsl:element>
<xsl:element
name="td">
<xsl:attribute
name="align">center</xsl:attribute>
<xsl:value-of
select="QuantityPerUnit" />
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:for-each>
</center>
</table>
<!-- Start Of Show previous/next page links-->
<!-- Show the previous page, only if
pageNumber>0 -->
<span style="Z-INDEX: 101; LEFT: 261px; WIDTH:
501px; POSITION: absolute;
TOP: 500px; HEIGHT:
62px">
<xsl:if
test="$pageNumber > 0">
<xsl:element
name="a">
<xsl:attribute
name="href">?pagenumber=<xsl:value-of
select="number($pageNumber)-1"
/>
</xsl:attribute> <<
Previous Page
</xsl:element>
 
     
</xsl:if>
<!-- Next page, do not show
when at end() of listing -->
<xsl:if
test="($recordCount - ((1+number($pageNumber)) * $recordsPerPage))>
0">
<xsl:element
name="a">
<xsl:attribute
name="href">?pagenumber=<xsl:value-of
select="number($pageNumber)+1"
/>
</xsl:attribute> Next
page >>
</xsl:element>
</xsl:if>
<!-- End
Of Show previous/next page links-->
</span>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
All that we have changed is the addition of the parameters and the Previous and Next links. At the time of defining the parameters, we also assign default values to them, which will come into play if the caller does not pass values to the stylesheet. The Next Page and Previous Page links allow us to navigate to the next or previous set of records.
At the top of the listing, we have declared the following variables.
<xsl:variable name="recordsPerPage" select="77" />
<!-- Page Number field -->
<xsl:variable name="pageNumber" select="0" />
<!--Record Count Field-->
<xsl:variable name="recordCount" select="77" />
These above-mentioned variables are used to define such characteristics as the number of records to be shown in a page, the current page number, and the total number of records contained in the Products table. Now that we have declared all the parameters, we are ready to start passing values to those parameters from the ASP.NET application.
How to supply parameters to an XSLT stylesheet
As mentioned earlier, in this section we will demonstrate how to supply parameters to the XSL stylesheet from an ASP.NET code-behind file. This capability requires the use of the XsltArgumentList class. We will examine some of the important methods and properties of this class before we go on to implement this class in our application.
XsltArgumentList class allows us to create XSLT reusable and maintainable stylesheets by providing a mechanism for passing parameters to the stylesheets. It also provides us with the ability to associate a class with the namespace URI, due to which we can call the methods of a class directly from a stylesheet. These objects whose methods are invoked from the stylesheet are called Extension objects. We will see an example of this in the next section.
The following list summarizes the important methods of the XsltArgumentList class.
- AddParam - As the name suggests, this method allows us to add parameters to the XsltArgumentList object.
- AddExtensionObject - This method is similar to the AddParam method except for the difference that this method allows us to add a new object to the XsltArgumentList object as opposed to adding a simple parameter. Once the object is added to the XsltArgumentList object and passed to the stylesheet, we can then seamlessly invoke the properties and methods of this object directly from the stylesheet.
For this example, let us add a new Web form named XslTransformExample2.aspx to the ASP.NET Web application. In the Page_Load event of the Web form, let us add the following lines of code.
private void Page_Load(object sender, System.EventArgs
e)
{
//Retrieve
the connection string from the Web.config file
string
connString =
System.Configuration.ConfigurationSettings.AppSettings["connectionString"];
SqlConnection
sqlConn = new SqlConnection(connString);
//Open the
connection to the database
sqlConn.Open();
//Instantiate
the SqlCommand object and pass the query to be executed
SqlCommand
sqlCommand = new SqlCommand("Select * from Products
for xml
auto,elements",sqlConn);
//Execute
the query
XmlReader
reader = sqlCommand.ExecuteXmlReader();
//Associate
the XmlReader object with the XPathDocument object
XPathDocument
xpathDoc = new XPathDocument(reader);
//Close the
connection to the database
sqlConn.Close();
XslTransform
transform = new XslTransform();
//Load the
XSL stylsheet into the XslTransform object
transform.Load(Server.MapPath("xmlpaging2.xsl"));
XsltArgumentList
argsList = new XsltArgumentList();
//Retrieve
the pageNumber from querystring
int
pageNumber = Convert.ToInt32(Request.QueryString["pagenumber"]);
//Add the
required parameters to the XsltArgumentList object
argsList.AddParam("recordsPerPage","",10);
argsList.AddParam("pageNumber","",pageNumber);
argsList.AddParam("recordCount","",77);
//Invoke
the transform method, passing in the XsltArgumentList object
transform.Transform(xpathDoc,argsList,Response.Output);
reader.Close();
}
In the above lines of code, we will consider only the lines of code that are different from the previous code example.
Here we create an instance of the XsltArgumentList.
XsltArgumentList argsList = new XsltArgumentList();
We then retrieve the value of the pagenumber that is passed in the query string.
//Retrieve the pageNumber from querystring
int pageNumber = Convert.ToInt32(Request.QueryString["pagenumber"]);
After that we add all the parameters to the XsltArgumentList object by invoking the AddParam method.
//Add the required parameters to the XsltArgumentList object
argsList.AddParam("recordsPerPage","",10);
argsList.AddParam("pageNumber","",pageNumber);
argsList.AddParam("recordCount","",77);
In this case, since we know the total number of records in the Products table, we have hard-coded the value for the recordCount parameter. Finally, we invoke the transform method of the XslTransform class, passing in all the required parameters including the XsltArgumentList object that contains the parameters required to implement paging. Since we want the output to be written to the client browser directly, we pass Response.Output to the third parameter, which indicates the stream to which the output should be written.
//Invoke the transform method, passing in the XsltArgumentList object
transform.Transform(xpathDoc,argsList,Response.Output);
With all these enhancements in place, pointing the browser to the URL of the Web form results in the following output.
The above page shows only 10 records per page. This is because of the recordsPerPage parameter, which is set to 10 in the above code. Now that we have seen how to pass parameters to an XSL stylesheet and control the number of records displayed in the page, we should look at XSLT Extension objects and illustrate how to use them in our application.