XSL treats all output as XML. Since there is no special treatment for generating HTML, <SCRIPT> and other features associated with Dynamic HTML can be generated as well. These display-time scripts are treated as text content by the XSL processor, and are executed only when interpreted by an HTML browser. This section shows some examples and hints to make generating dynamic HTML easier.
The <SCRIPT> element is one area where HTML and XML parsing rules clash. In HTML, < and > do not need to be escaped to < and > within a script block. Indeed, if they are, the script will usually break. However, these same characters must be escaped in well-formed XML such as that output by the XSL processor. XSL cannot generate the non-well-formed output expected by HTML.
Fortunately, there is a workaround. Place script inside a comment block and it will conform both to the well-formedness rules of XML and will be correctly interpreted by browsers, which generally support this syntax for backward compatibility with prescriptable browsers. Just as when including script in <xsl:script>, the script content should also be enclosed in a CDATA section to ensure that special characters and white space are preserved.
<SCRIPT><xsl:comment><![CDATA[
// checks a number against 7
function less-than-seven(n) {
return n < 7;
}
]]>//</xsl:comment></SCRIPT>
This code generates:
<SCRIPT><!--
// checks a number against 7
function less-than-seven(n) {
return n < 7;
}
//--></SCRIPT>
Note that the final // before the closing comment prevents the characters --> from being interpreted as script in some older browsers. This is not necessary when authoring style sheets for use only in newer browsers.
The following style sheet generates a <SCRIPT> element in the output document that allows the user to highlight an element by clicking the output from that element.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<HTML>
<HEAD>
<SCRIPT LANGUAGE="JSCRIPT"><xsl:comment><![CDATA[
function hiLite()
{
e = window.event.srcElement;
if (e.style.backgroundColor != 'yellow')
e.style.backgroundColor = 'yellow';
else
e.style.backgroundColor = 'white';
}
]]></xsl:comment></SCRIPT>
</HEAD>
<BODY>
<xsl:for-each select="grocery-list/item">
<DIV STYLE="background-color:yellow" onClick="hiLite()">
<xsl:value-of/>
</DIV>
</xsl:for-each>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
The onClick attribute and the <SCRIPT> blocks are treated as output attributes and elements by XSL. The scripts are not executed until a browser displays the resulting HTML.
Display-time scripts can become quite complex to author within a style sheet. Often it is easier to author a prototype of the HTML page first to develop and debug the dynamic behavior. When the behavior is working correctly, it can be added to the style sheet.
The script in the above example is executed at display time by the browser. In addition, a style sheet can contain transformation-time script that is executed by the XSL processor. There is no direct communication possible between these two types of script because the processes of transforming to HTML and displaying the HTML occur serially.
Indirect communication from transformation-time scripts to display-time scripts is possible. Either the XSL transformation can manipulate or generate the display-time script directly, or the XSL transformation can place information in the resulting HTML that the display-time scripts can use—commonly ID or class attributes.
The following example shows how transformation-time scripts can indirectly pass information to display-time scripts.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<HTML>
<HEAD>
<SCRIPT LANGUAGE="JSCRIPT"><xsl:comment><![CDATA[
function hiLite(normalColor, hiliteColor)
{
e = window.event.srcElement;
if (e.style.backgroundColor == hiliteColor)
e.style.backgroundColor = normalColor;
else
e.style.backgroundColor = hiliteColor;
}
]]></xsl:comment></SCRIPT>
</HEAD>
<BODY>
<xsl:for-each select="grocery-list/item">
<DIV>
<xsl:attribute name="STYLE">
background-color:<xsl:eval>whichColor(this)</xsl:eval>
</xsl:attribute>
<xsl:attribute name="onClick">
hiLite('<xsl:eval>whichColor(this)</xsl:eval>',
'<xsl:eval>selectedColor(this)</xsl:eval>')
</xsl:attribute>
<xsl:value-of/>
</DIV>
</xsl:for-each>
</BODY>
</HTML>
</xsl:template>
<xsl:script><![CDATA[
function even(e) {
return childNumber(e) % 2;
}
function whichColor(e) {
if (even(e))
return "#ddffdd";
else
return "#ffffff";
}
function selectedColor(e) {
if (even(e))
return "#bbddbb";
else
return "#dddddd";
}
]]></xsl:script>
</xsl:stylesheet>
At transformation time, the whichColor function in the <xsl:script> element generates the initial background color of each item and the parameters of the call to hiLite. At display time, the hiLite function in the <SCRIPT> element allows the user to then click an item to change its color, based on the parameters dynamically generated by the style sheet.