
XSLT, Browsers, and JavaScript
by Bob DuCharmeFebruary 05, 2003
Web browsers, however, usually read a document from a web server and have no way to separately be told about the stylesheet to apply. To remedy this, the W3C Recommendation Associating Style Sheets with XML Documents describes a processing instruction to include at the beginning of a document to name a stylesheet to apply to that document. For example, the processing instruction in the following numbers.xml document tells an application to apply the stylesheet squareAsHTML.xsl to that document.
<?xml-stylesheet href="squareAsHTML.xsl" type="text/xsl" ?>
<numbers>
<number>2</number>
<number>11</number>
<number>100</number>
<number>-5</number>
</numbers>
This processing instruction must be at the very beginning of a document, unless there is an XML declaration before it. Below is the squareAsHTML.xsl stylesheet referenced by the processing instruction above:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<!-- squareAsHTML.xsl: create an HTML document with a statement
about the square of each "number" element read from the
source tree. -->
<xsl:template match="/"> <!-- Set up web page -->
<html>
<head>
<title>Squares</title>
<style> <!-- Put a little CSS in -->
body { font-family: arial,helvetica; }
h1 { font-size: 14pt }
p { font-size: 10pt}
</style>
</head>
<body>
<h1>Squares</h1>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="number">
<xsl:variable name="value" select="."/>
<p>
<xsl:text>The square of </xsl:text>
<xsl:value-of select="$value"/>
<xsl:text> is </xsl:text>
<xsl:value-of select="$value * $value"/>.</p>
</xsl:template>
</xsl:stylesheet>
(If you're using XSLT to create result documents with processing
instructions in them, see the earlier column XSLT,
Comments and Processing Instructions for information on XSLT's
xsl:processing-instruction instruction.) Using a command-line
XSLT processor such as Saxon or Xalan to apply the squareAsHTML.xsl
stylesheet to the numbers.xml document creates the following HTML
document:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Squares</title><style>
body { font-family: arial,helvetica; }
h1 { font-size: 14pt }
p { font-size: 10pt}
</style></head>
<body>
<h1>Squares</h1>
<p>The square of 2 is 4.</p>
<p>The square of 11 is 121.</p>
<p>The square of 100 is 10000.</p>
<p>The square of -5 is 25.</p>
</body>
</html>
|
Related Reading
XSLT Cookbook |
The best thing about specifying a document's stylesheet with this
xml-stylesheet processing instruction is that it lets you use
the document and designated stylesheet with a web browser. With the
numbers.xml document and stylesheet shown above both sitting in the
same directory of your hard disk, you can tell the current versions of
Mozilla and Internet Explorer to open up numbers.xml and you'll see
the result of the transformation. The rendered result should look the
same as if you had opened an HTML file created by a command-line XSLT
processor using the same input and stylesheet files. (The
command-line processor Saxon does let you specify a
command-line switch telling it to look for the stylesheet name in
this processing instruction.)
You could also put the XML document and stylesheet on a web server, as I did here. Follow that link, and you should see the result of the stylesheet being applied to the XML document. After doing so, try a View Source, and you'll see the untransformed XML document with a slight change: I renamed the server copy of the stylesheet to squareAsHTML.xml, even though it's the exact same stylesheet file. As I write this, my web server's host provider ships XSLT stylesheets with a MIME type of text/html, so Mozilla treats them as HTML files. (I've suggested that they send them as text/xml.) When I give the stylesheet an extension of "xml", their server ships it with a MIME type of text/xml, so Mozilla knows that it's not HTML and uses its TransforMiiX XSLT processor to apply the stylesheet to the document and then renders the result in the browser.
As long as it's going to be rendered in a browser, you may as well take advantage of other features that modern browsers offer. My XSLT stylesheet above added a little CSS stylesheet to the rendered HTML to set the fonts of the output. By including JavaScript code with your result HTML, you can take advantage of client-side processing to add interactivity to the web pages that get created by your XSLT stylesheet.
Outputting HTML with JavaScript
The following stylesheet resembles the previous one, except that
its head element has a script child element along
with the title and style child elements. JavaScript
code in this script element declares a function that displays
a message box showing the square of the number passed to the
function. If you pass it the number 3, the message box will say "the
square is 9."
For each number element read from the input, instead of
figuring out the square of the number, the second template rule adds a
button to the form created by the first template rule. When clicked,
this button calls the function declared in the script
element.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<!-- squareAsHTMLJS1.xml: create an HTML document with JavaScript that
interactively computes the square of each "number" element read from
the source tree. -->
<xsl:template match="/"> <!-- Set up web page -->
<html>
<head>
<title>Squares</title>
<script language="JavaScript1.2">
function showSquare(n) {
alert("the square is " + n*n);
}
</script>
<style> <!-- Put a little CSS in -->
body { font-family: arial,helvetica; }
h1 { font-size: 14pt }
p { font-size: 10pt}
</style>
</head>
<body>
<h1>Squares</h1>
<p>Click a button to see the square of that number.</p>
<form>
<xsl:apply-templates/>
</form>
</body>
</html>
</xsl:template>
<xsl:template match="number">
<p><input type="button" value=" {.} " onClick="showSquare({.})"/></p>
</xsl:template>
</xsl:stylesheet>
|
Also in Transforming XML | |
To see this stylesheet in action, send your browser to this variation on the numbers.xml document from above. Its only difference from the original numbers.xml file is that it points to this new XSLT stylesheet. (Don't take my word for it -- do a View Source to see.) Again, the stylesheet has an extension of "xml" so that it works as well with Mozilla as it does with IE.
Putting a lot of JavaScript code inside of a script
element in an XSLT template can get messy, so it's often convenient to
store it in a separate file and then reference it with the
script element's src attribute. This final
variation on numbers.xml points to a stylesheet
that does just that; it looks like the stylesheet above, but its
script element has an src attribute that points to a
squareAsHTMLJS2.js file. The showSquare() code is stored in
squareAsHTMLJS2.js instead of being between the
<script></script> tags in the XSLT stylesheet.
Keeping your JavaScript code in a separate file is cleaner, but
putting it between the <script></script> tags gives you
a powerful opportunity: you don't have to hardcode your JavaScript
code in your XSLT stylesheet; you can write XSLT logic to generate
JavaScript code based on dynamic conditions such as values in your
input. Next month, we'll see how this can let you turn nested
a elements in an XHTML source document into one-to-many links
implemented as pop-up menus in the rendered result.
Have you used XSLT to emit JavaScript-enabled HTML pages? Share your experience in our forums.
(* You must be a member of XML.com to use this feature.)
Comment on this Article
| Titles Only | Titles Only | Newest First |
- How to send 2 paramters to javascript function
2006-12-03 22:45:01 SaichandKamisetty [Reply]
For 1 parameter i have used this code :
javascript:showNPSData({./SC_DF_FIELD_1});
But for sending of 2 paramters its not accepting this form
javascript:showNPSData({./SC_DF_FIELD_1},{./SC_DF_FIELD_1})
Can you plz help me ?
- what about the browsers supporting the XSLT templates?
2004-06-29 21:28:42 Navdeep [Reply]
Which are the browsers who support fully, the XSLT templates without any extra XML parser like MSXML?
like IE 5.5,Netscape 6 does not support XSLT. how about the new browsers. do they have builtin parsers to parse XSL?
thanks
Navdeep
- what about the browsers supporting the XSLT templates?
2004-06-30 06:15:34 Bob DuCharme [Reply]
I'm not sure what you mean by the XSLT templates. Virtually all XSLT stylesheets have template rules. Also, all XSLT processors need an XML parser, but now that's included with most operating systems (or with the XSLT parsers). With older versions of IE, you needed to add the MSXML.DLL to your Windows setup.
IE 6.0 and Mozilla 1.6 support client-side XSLT just fine; is that what you meant by "the new browsers"?
Bob
- what about the browsers supporting the XSLT templates?
- what if scripts and styles are defined in external files?
2004-04-13 04:44:08 matek994 [Reply]
what if scripts and styles, used in the xslt-templates are located in external files?
is this possible.
i get problems here... having the xml-file to be transformed in one folder, and the rest, i.e. xslt-stylesheet css-stylesheet and js-document in a subdirectory, referencing these becomes difficult.
including the hmtl tag <script src..> and <link href=..css..>, and using relative uri:s leads me into trouble. the relative uri:s are resolved based on the uri for the xml-file, and not for the xslt file...!!!!
help!?!!
/mats
- xslt and javascript
2003-03-21 01:40:19 veronique dupal [Reply]
Hi,
How can I use an array as a variable in an XSLT document and then send it as an parameter to a javascript function.
Thanks in advance
- xslt and javascript
2006-12-12 01:03:34 xslt&javascript [Reply]
hi
Prasently i am converting crystal reports into web reports using xml and xslt.In xslt td tag i write a Onclick property i pass a one java script function.In function i pass a td value and that td value passed into another xslt as a parameter.
how to pass the td value into another xslt.
pls send the correct solution to me as early as possible.
Thanks & Regards
Krishna
Software engineer.
- xslt and javascript
2003-03-21 05:35:39 Bob DuCharme [Reply]
I've never tried this. I suggest that you ask on the XSL-list at http://www.mulberrytech.com/xsl/xsl-list/. There are many, many XSLT people watching the list, and you may get an answer very quickly.
- xslt and javascript
- Watch out with output escaping...
2003-03-20 18:00:26 Frederik Willaert [Reply]
Hello,
A "caveat" I ran into when producing JavaScript with XSLT...
As you may have read in the thread about "CDATA", you can simply write e.g. "<" in order to get "<" in the JavaScript output. However, it appears that this only works correctly when the output method is set to "html", either by:
- explicitly setting the output method to "html" on the <xsl:output> element
- making sure that the output document has <html> as its root element, and either there is no <xsl:output> element in your stylesheet, or it has the value "html" - in this case, the XSLT processor defaults to the html output method, as the XSLT spec explains.
Either way, output escaping is only disabled for the content of the <script> and <style> tags (again, see the XSLT spec, http://www.w3.org/TR/xslt#section-HTML-Output-Method).
If you _have_ to use the xml output method, an alternative is to use <xsl:text disable-output-escaping="yes">, but this soon gets messy.
I've been experimenting a bit with the different possibilities (using MSXML4.0, by the way), but I still may have missed something - tell me. I should read that XSLT spec a bit more thoroughly, I guess...
Frederik Willaert
PS. I know this post has something to do with the CDATA thread, but I thought this could be considered as a separate topic...
- Scripts need CDATA too
2003-02-13 07:05:51 Taylor Cowan [Reply]
Bob, I want to add that we need to use CDATA with larger scripts, and any non-xml text in general.
This would cause a problem:
<script language="JavaScript1.2">
function showWhyWeNeedCdata {
if ( 1 < 2 )
alert("scripts need CDATA");
}
</script>
Yours were fine, but we run across <,>, and sometimes & in scripts.
Taylor Cowan
- Scripts need CDATA too
2003-02-13 11:47:34 Bob DuCharme [Reply]
I find that nearly all uses of CDATA are kludges. Here are some other things you can do:
1. Use entity references for those characters. I've pasted a script below that worked with Mozilla 1.2.1 and IE 6.0 under Win98.
2. Put the script in a separate file.
(The latter choice may not be an option if the script makes use of data from the source document, which is something I'll demonstrate in my next column.)
Bob
<!-- load the following short document into your browser as an XML file -->
<?xml-stylesheet href="test1.xsl" type="text/xsl" ?>
<x/>
<!-- here is test1.xsl -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<html>
<head>
<title>test</title>
<script language="JavaScript1.2">
function showWhyWeNeedCdata() {
if ( 1 < 2 )
alert("scripts rarely need CDATA");
}
</script>
</head>
<body><form>
<input type="button" value=" go " onClick="showWhyWeNeedCdata()"/>
</form>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
- Scripts need CDATA too
2003-03-16 05:20:41 drefty mcphooter [Reply]
Your remark "I find that nearly all uses of CDATA are kludges..." is probably consistent with someone who has strong knowledge, affinity and preference for XSLT, but perhaps it is also good to remember that not everyone shares the same affinity. Here are some reasons why CDATA might not be a "kludge"
1. What if you have a tool that 'autogenerates' both XSLT *and* the enclosed JavaScript in <script></script> tags? You cannot rely on a simple 'search and replace' to insert entity references, because it will produce unpredictable results. (a common scenario in computer programming that I call 'The delimiter collision problem').
2. You yourself experienced the problem where you wanted to show < but the browser interpolated the entity reference when you didnt intend it to ('The delimiter context problem').
3. What if the insertion of entity references renders the JavaScript code unreadable (either by a human being, or other agent, such as a JavaScript debugger or IDE)? Many people dislike XSLT when it is written in such a way that it is difficult to tell what the transformation will look like just by looking at the XSLT itself. ('The template round-tripping problem' and 'The template transparency problem').
I, for one, am glad that XSLT has a facility such as CDATA, because it's reasonable to assume that 'quick and dirty' does not always mean 'kludge'. One person's 'kludge' is another person's preference for getting work done faster.
And afterall, you could say that *all* computer software is a 'kludge' for something that a person would rather be able to do without having to use a computer at all.
NOTE: buzzwords like "kludge" and "elegant" get tossed around all the time with no definition. Here, I define "kludge" as: "A use of a tool in a manner that is dramatically inconsistent with the intentions and goals of the people who designed the tool, the end result being an increase in the tedium and difficulty of maintenance." Also implied with the term 'kludge' is the principle that the perpetrator is not knowledgable about the subtleties of the tool itself.
- Scripts need CDATA too
2003-03-17 19:17:47 Bob DuCharme [Reply]
I have seen CDATA used to solve problems that couldn't be solved better any other way--for example, sending XML that includes a DOCTYPE declaration as part of a SOAP message.
I have seen CDATA used in many different contexts, and the ones that qualify as solving problems that couldn't be solved any other way were a tiny minority. That's why I said that *nearly* all uses of CDATA are kludges.
Bob
- Scripts need CDATA too
- Scripts need CDATA too
2003-02-13 11:48:46 Bob DuCharme [Reply]
In the example that I posted, the if condition should have been (1 < 2), but when I posted it, the entity reference got converted.
- Scripts need CDATA too
- Scripts need CDATA too
- is there a way to have XSLT not check script for tags?
2003-02-07 16:19:11 lee davis [Reply]
E.g. I have three routines
function Odd(){document.writeln("<tr class="RO" ... function Evn(){document.writeln("<tr class="RE" ...
function rowEnd(){document.writeln("</tr>" ...
which I programitcall call properly. But the XSLT complains because there are unmatched <tr> tags in the above code even though I will call the odd for half the rows, evn for half and rowend for all.
Is there a way to tell it to not check the javascript it will produce?
2003-02-07 05:47:22 ard schrijvers [Reply]
- Performance Metrics in Internet Explorer
2003-02-06 17:10:03 John Allen [Reply]
Do you have any performance metrics on rendering a much larger example (1MB, 10MB, 50MB, ?) of this by using ActiveX objects to load, transform and render this versus embedding the JavaScript in the XSLT? It would would be valuable to know if pulling both the xml and xsl files into an HTML document, processing it and outputting it into a <div> is faster than the method you describe.
- Performance Metrics in Internet Explorer
2003-02-07 06:23:31 Bob DuCharme [Reply]
It might be. It's a different approach to this kind of processing with its own potential optimizations and limitations. Metrics would be difficult to gather because of the number of variables involved; someone would have to test these based on their own environment to make a proper comparison.
- Performance Metrics in Internet Explorer
- Server-side processing is better
2003-02-05 21:47:27 Nasseam Elkarra [Reply]
Referencing stylesheets from within XML documents is not the optimal method for transformations. This method depends on the widespread adoption of browsers supporting the XSL recommendation--something you cannot count on if you are a webmaster. By using the server's ability to detect the client's browser, you can have one XML file and apply a specific stylesheet based on the client profile. This allows the XML document on the server to be transformed using a specific stylesheet and then sent to the client as pure XHTML, WML, etc. Using the server's power to transform will also benefit slow connections and small devices. The benefits of server-side processing easily outweigh those of client-side processing. This fact should make server-side processing the preferred method for transformations and a possible candidate for a future article, no?
Nasseam Elkarra
http://www.myspotter.com
