Converting from XSL to XSLT and the context() Operator
I'm having trouble converting an old Extensible Stylesheet Language (XSL) style sheet to Extensible Stylesheet Language Transformations (XSLT). The style sheet takes an arbitrary XML-formatted data set that ADO's Save method produces and builds an HTML table (including column headers) with the data. I tried to use the XSL context() operator, but XSLT doesn't support that operator. Without using the context() operator, how do I access data values from previous selections that have occurred within the style sheet? I'm also having difficulty formatting date fields. How can I obtain a user-defined date format in XSLT?
The context() operator is one of the features that XSL supports but that XSLT doesn't support. (For background information about XSL and its trip through the wilds of becoming a standard, see the Web-exclusive sidebar "XSL to XSLT: Terminology and Background." See "More on the Web," page 48, for instructions.) The context() operator provided access to previous context nodes in the source document's query hierarchy. The source document is the XML document that you apply the style sheet to. The query hierarchy is the set of selections that occurs within the style sheet as the style sheet processes the source document. Selections occur when an XSL style sheet executes xsl:for-each, xsl:apply-templates, or other elements that change the node that the style sheet is processing.
For example, if I have a template within a style sheet that matches the root element, then uses an xsl:for-each element to iterate through the root element's children, the root element represents the first context node in the query hierarchy. As the xsl:for-each element processes the root element's children, each child in turn becomes the second context node. When executing an XSL style sheet, the XSL engine maintains the query hierarchy in a stack of context nodes that the context() operator can access.
Listing 1 shows an example of the XSL style sheet, which builds an HTML table by using an XML document output containing data from an ADO Recordset. The XML document is produced by ADO's Recordset.Save() method. The style sheet produces the header row for the HTML table from the XML Data Reduced (XDR) schema that ADO included in XML. Each AttributeType definition, which defines an XML attribute to hold the data from a column of the recordset, in the XDR schema represents a table column. Web Figure 1 shows an example of the XML output from ADO.
The XSL style sheet uses two templates: one to build the table, including the column headers, and the other to build the individual rows in the table. The first template, at callout A in Listing 1, produces the column headers, using the order-by attribute to sort the headers alphabetically. After producing the column headers, the style sheet executes another template, which sorts and processes all row elements by calling
<xsl:apply-templates select="/xml/rs:
data/z:row" order-by="@CustomerID" />
The xsl:apply-templates element instructs the XSL engine to find a matching template for each z:row element in the XML document. The order-by attribute sorts the rows by CustomerID. Then, the template at callout B in Listing 1 is executed for each row.
To ensure that the table displays the data columns in the same order as the header columns, the template at callout B iterates through the AttributeType definitions, sorted by name, in the XDR schema by using the xsl:for-each element. As the xsl:for-each element selects each AttributeType, the context node changes to the node corresponding to the AttributeType, instead of the row element that the template at callout B is processing that contains the data we're attempting to access and output. In other words, because the xsl:for-each element introduces a new context, you have to use the context() operator in the xsl:value-of element at callout B to select the attribute that contains the data for the correct column in the HTML table.