Dynamic Generation of Dynamic HTML By XSLT
by K. Yue
December, 2002
copyright 2002
First draft: December 10, 2002
1. Introduction
XSLT (eXtensible Stylesheet Language Transformations) [1] is a powerful language for transforming XML documents. Data contents stored in XML documents can be extracted and transformed to the desirable output formats, such as XML, HTML or plain text. XSLT has therefore a central role in utilizing XML technologies to separate data contents from presentation.
As a declarative rule-based language, many developers may find XSLT difficult to grasp. Moreover, since XSLT can be used to output different formats, additional considerations will be required to ensure that the XSLT output satisfies the syntax and semantics of the output format.
A very common usage of XSLT is to generate HTML code to be viewed by the Web browser. Since Javascript can be embedded within HTML, XSLT can be used to dynamically generate dynamic HTML code to improve the page's interactivity and navigation. Developing these applications will not be straightforward as the XSLT program will need to taken into accounts of the followings:
A simplified architecture for these applications using JSP and XSLT is shown in the following figure.

It can be seen that the XSLT program needs to consider HTML, Javascript, JSP and the source XML document. Furthermore, functionality can be implemented in either the client side using Javascript and HTML, or in the server side by JSP and XSLT logic. The blurring of client side and server side functions can further confuse developers.
In this article, I will present some guidelines for developing XSLT program for generating dynamic HTML. These guidelines are illustrated by a simple problem to be explained in Section 2. Section 3 presents the guidelines alongside with the developing solution. Section 4 is our conclusion. I assume that the readers are reasonably familiar with HTML, Javascript, XSLT and JSP.
2. The Problem: Newsfeed Display
Many Websites now include newsfeed on topics interesting to the visitors. I am going to develop a JSP program to use XSLT to dynamically generate a simple newsfeed page for different countries. The page is vastly simplified so it can be presented in its entirety here. However, it can easily be adapted to satisfy different needs. The JSP program accepts one HTTP parameter "country" which is the name of the country the user wants to get news from. When accessed, the browser should initially display the following page, assume that China is the country selected.
http://myserver.com/news.jsp?country=China

Clicking the "More China News" button displays the next news headline in a cyclic manner:

The JSP program gets real-time newsfeed from an XML news server (that is based on http://w.moreover.com/):
http://dcm.cl.uh.edu/yue/courses/xml/server/newsServer.pl?country=China
The news server accepts a single HTTP parameter "country" and return the news headline XML:
<?xml version="1.0"?>
<!--
News for topic China.
The news have been updated within the last 1 hours.
-->
<news>
<country>China</country>
<entry num="_1">
<headline>Shanghai wins bid to
host 2010 World Expo</headline>
<harvesttime>Dec 5 2002 9:08PM</harvesttime>
<url>http://www.chinaonline.com/</url>
</entry>
<entry num="_2">
<headline>Net sites blocked by
China go from expected to bizarre</headline>
<harvesttime>DEC 5 2002 7:49PM</harvesttime>
<url>http://www.boston.com/globe/business/</url>
</entry>
<entry num="_3">
....
The problem will be implemented by using XSLT to generate the dynamic HTML program. XSLT 1.0 [5] will be used since XSLT 2.0 [6], despite much more powerful, is only a working draft and not a recommendation.
3. Development Guidelines and Solution
To tackle the complexity of any non-trivial problem, it is necessary to break down the problem into smaller pieces that are as independent as possible. These smaller subproblems can then be solved completely before the next subproblem. Errors from different sources, such as Javascript, HTML, JSP and XSLT, may interact to make debugging difficult. Dividing into independent subproblems minimize error coupling.
For dynamic generation of dynamic HTML using XSLT, the following steps are recommended.
These steps will be addressed in the following subsections with recommended tips.
Because of the limitation of space, the solution does not include error handling, such as when the XML news server does not return any news items, or when the required HTTP parameter "country" is absent. Appropriate error handling can be added easily.
3.1 Develop a sample dynamic HTML program
Cross browser dynamic HTML programs are known to be difficult to develop, especially when a wide range of browsers are targeted. It is therefore important to develop and thoroughly test the client side code that should be generated by the XSLT program. Failing to do so may mean the developer will need to worry about dynamic HTML and XSLT code at the same time, making the task much more difficult.
In this first step, a typical sample is constructed using typical data. In our newsfeed example on China, and there may be four headline news:
The page should therefore looks like the following initially:

Clicking the "More China News" button displays:

The dynamic HTML code for the page is shown below.
samplenews.html:
<html>
<head>
<title>China News</title>
<script language="Javascript">
<!-- Hide scripts from older browsers.
function nextNews()
{ nextNews.count++;
if (nextNews.count >= nextNews.News.length)
{ nextNews.count = 0;
}
return nextNews.News[nextNews.count];
}
nextNews.News = new Array(
"ex-President Jiang confirmed to love chocolate.",
"Primer Zhu's long lost pet found!",
"Shanghai endorses zoning.",
"Hong Kong ranks first in VSOP consumption."
);
nextNews.count = nextNews.News.length-1;
function showNews() {
document.getElementById('news').innerHTML = nextNews();
}
// -->
</script>
</head>
<body style="background-color:#ccccff;font-family:verdana;font-size:10pt"
onLoad="showNews()">
<p>
China news:
</p>
<div id="news" style="background-color:#FEFFD9; width:600;"></div>
<p>
<form onSubmit="showNews(); return false; ">
<input type="button" value="More China News" onClick="showNews()" />
</form>
</p>
</body>
</html>
The array nextNews.News stores the news items as string elements. The function nextNews returns the news items in a cyclic manner. Upon clicking, the button "More China News" invokes the function showNews(). The function showNews() uses Javascript DOM (Document Object Model) [5] to access the <div> element with id "news" and display the news item there by setting its innerHTML property. Although the innerHTML property is a Microsoft's extension on W3C DOM, it is supported by most browsers. The onLoad event handler also calls the showNews() function to ensure the appearance of the first news item when the page is initially displayed.
The code has been tested in Internet Explorer 5+, Nescape 6+ and Mozilla 1+. It does not work on Netscape 4.x. However, porting to Netscape 4.x will not be difficult.
Since this is a highly simplified example, the dynamic HTML code is relatively simple. In a more sophisticated application, there would be much more demanding development, testing and debugging. Focusing on the client side code using a typical sample allows to ensure that it is well tested and that it satisfies the user requirements.
3.2 Set up the server side program for invoking XSLT
This is a relatively easy step. The server side program needs to get the value of the HTTP parameter "country" and use it to obtain the XML news document from the XML news server. In our example, we use JSP and the following simple code will do the job:
news.jsp:
<%@ page import="javax.xml.parsers.*" %><%@
page import="javax.xml.transform.*"
%><%
String xmlSourceUrl = "http://dcm.cl.uh.edu/yue/courses/xml/server/newsServer.pl?country=";
String xslSourceFilename = application.getRealPath("/paper/xslt/news0.xsl");
xmlSourceUrl += request.getParameter("country");
response.setContentType("text/html");
out.clear();
// Transform and output.
try
{
javax.xml.transform.TransformerFactory tFactory =
javax.xml.transform.TransformerFactory.newInstance();
// Get the XML input document and the stylesheet, both
in the servlet
// engine document directory.
javax.xml.transform.Source xmlSource =
new javax.xml.transform.stream.StreamSource
(new java.net.URL(xmlSourceUrl).openStream());
javax.xml.transform.Source xslSource =
new javax.xml.transform.stream.StreamSource
(new java.net.URL("file:" +
xslSourceFilename).openStream());
// Generate the transformer.
javax.xml.transform.Transformer transformer =
tFactory.newTransformer(xslSource);
// Perform the transformation, sending the output to
the response.
transformer.transform(xmlSource,
new javax.xml.transform.stream.StreamResult(out));
}
// If an Exception occurs, return the error to the client.
catch (Exception e)
{
out.write(e.getMessage());
}
// Close the PrintWriter.
out.close();
%>
The page import directive imports the two Sun's JAXP packages [8] required
for XML parsing and XSLT transformation. The source XML URL (sourceXmlUrl) is
prepared by appending the URL of the XML news server by the country name obtained
from the HTTP parameter "country". The XSLT file name (sourceXslFilename)
is hardcoded to be "newsp0.xsl" in this example. The try block is
used to apply the XSLT transformation and send the output to the Web server
using the JSP built-in object out.
The XSLT program news0.xsl contains the bare minimum to show that the JSP program is working appropriately:
news0.xsl:
<?xml version='1.0'?>
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="html" version="4.0"
indent="yes"
/>
<xsl:template match='/'>
<html>
<body style="background-color:#ccccff;font-family:verdana;font-size:10pt"
onLoad="showNews()">
Test.
</body>
</html>
</xsl:template>
</xsl:stylesheet>
The body of the only template for the document root ("/") outputs constant HTML code with a simple "Test" that looks like:

This simple step ensures that the JSP is set up appropriately and the remaining task will focus only on the XSLT program.
3.3 Develop the XSLT program for generating the sample dynamic HTML code
The next step is to modify the XSLT program so it will generate the sample dynamic HTML program developed in step (1). This is a easy but worthy step. XSLT can be used to generate different output formats, which may have different syntactic and semantic requirements. This step can catch some of related problems early.
In this example, it may appear that all we need to do is replacing the constant HTML code by that of the sample dynamic HTML program in step (1). The new XSLT program with changes highlighted is shown below.
news1.xsl:
<?xml version='1.0'?>
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="html" version="4.0"
indent="yes"
/>
<xsl:template match='/'>
<html>
<head>
<title>China News</title>
<script language="Javascript">
<!-- Hide scripts from older browsers.
Function nextNews()
{ nextNews.count++;
if (nextNews.count >= nextNews.News.length)
{ nextNews.count = 0;
}
return nextNews.News[nextNews.count];
}
nextNews.News = new Array(
"ex-President Jiang confirmed to love chocolate.",
"Primer Zhu's long lost pet found!",
"Shanghai endorses zoning.",
"Hong Kong ranks first in VSOP consumption."
);
nextNews.count = nextNews.News.length-1;
function showNews() {
document.getElementById('news').innerHTML = nextNews();
}
// -->
</script>
</head>
<body style="background-color:#ccccff;font-family:verdana;font-size:10pt"
onLoad="showNews()">
<p>
China news:
</p>
<div id="news" style="background-color:#FEFFD9; width:400;"></div>
<p>
<form onSubmit="showNews(); return false; ">
<input type="button" value="More China News" onClick="showNews()" />
</form>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Using this XSLT program will display the following:

The page looks fine except that the initial news headline is missing. Clicking the "More China News" button produces a Javascript runtime error, confirming the suspicion. A good tip at this point is to analyze the source code generated by the XSLT program to detect the discrepancy with the targeted dynamic HTML file:
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>China News</title>
<script language="Javascript"></script>
</head>
<body onLoad="showNews()" style="background-color:#ccccff;font-family:verdana;font-size:10pt">
<p>
China news:
</p>
<div style="background-color:#FEFFD9; width:400;" id="news"></div>
<p>
<form onSubmit="showNews(); return false; ">
<input onClick="showNews()" value="More China News" type="button">
</form>
</p>
</body>
</html>
It can be seen very easily that the Javascript code inside the script element is now missing. This is simply because the HTML comment enclosed by <!-- and --> is also a comment to XSLT, which is ignored and not sent to the output. The best solution is to use CDATA section to encode that part.
news2.xsl:
<?xml version='1.0'?>
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="html" version="4.0"
indent="yes"
/>
<xsl:template match='/'>
<html>
<head>
<title>China News</title>
<script language="Javascript">
<![CDATA[
<!-- Hide scripts from older browsers.
Function nextNews()
{ nextNews.count++;
if (nextNews.count >= nextNews.News.length)
{ nextNews.count = 0;
}
return nextNews.News[nextNews.count];
}
nextNews.News = new Array(
"ex-President Jiang confirmed to love chocolate.",
"Primer Zhu's long lost pet found!",
"Shanghai endorses zoning.",
"Hong Kong ranks first in VSOP consumption."
);
nextNews.count = nextNews.News.length-1;
function showNews() {
document.getElementById('news').innerHTML = nextNews();
}
// -->
]]>
</script>
</head>
<body style="background-color:#ccccff;font-family:verdana;font-size:10pt"
onLoad="showNews()">
<p>
China news:
</p>
<div id="news" style="background-color:#FEFFD9; width:400;"></div>
<p>
<form onSubmit="showNews(); return false; ">
<input type="button" value="More China News" onClick="showNews()" />
</form>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
3.4 Develop the XSLT program for dynamic generation
In this step, the XSLT program is modified to dynamically generating the output dynamic HTML code. It begins with an analysis of the sample dynamic HTML file of step (1) to determine the parts that should be dynamically generated by XSLT. In our example, this is highlight below.
<?xml version='1.0'?>
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="html" version="4.0"
indent="yes"
/>
<xsl:template match='/'>
<html>
<head>
<title>China News</title>
<script language="Javascript">
<!-- Hide scripts from older browsers.
Function nextNews()
{ nextNews.count++;
if (nextNews.count >= nextNews.News.length)
{ nextNews.count = 0;
}
return nextNews.News[nextNews.count];
}
nextNews.News = new Array(
"ex-President Jiang confirmed to love
chocolate.",
"Primer Zhu's long lost pet found!",
"Shanghai endorses zoning.",
"Hong Kong ranks first in VSOP consumption."
);
nextNews.count = nextNews.News.length-1;
function showNews() {
document.getElementById('news').innerHTML = nextNews();
}
// -->
]]>
</script>
</head>
<body style="background-color:#ccccff;font-family:verdana;font-size:10pt"
onLoad="showNews()">
<p>
China news:
</p>
<div id="news" style="background-color:#FEFFD9; width:400;"></div>
<p>
<form onSubmit="showNews(); return false; ">
<input type="button" value="More China News"
onClick="showNews()" />
</form>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Next, the source XML is studied for the required data extraction. In our example, the XML news server has a DTD:
news.dtd:
<!ELEMENT news (country, entry*)>
<!ELEMENT country (#PCDATA)>
<!ELEMENT entry (headline, harvesttime, url)>
<!ELEMENT headline (#PCDATA)>
<!ELEMENT harvesttime (#PCDATA)>
<!ELEMENT url (#PCDATA)>
<!ATTLIST entry num ID #REQUIRED>
There are three occurrences of the country name "China", which should now be dynamically obtained from the value of the element <country>: <xsl:value-of select="//country" />. If the country name were not available from the source XML, it would be necessary to get the value from the HTTP parameter "country" via the JSP program and pass it as a parameter to the XSLT program.
Since there are three occurrences, it is appropriate to define an XSLT variable.
<xsl:variable name="country">
<xsl:value-of select="//country" />
</xsl:variable>
Subsequent retrieval of the country name can simply be done by referencing the variable (which is preceded by the "$" character in XSLT.)
<xsl:value-of select="$country" />
The last reference to the country name requires a little more consideration.
<input type="button" value="More China News" onClick="showNews()"
/>
The country name is inside the value of the attribute "value" and the following direct reference to the $country variable will not be XML well-formed.
<Input type="button" value="More <xsl:value-of select="$country"
/>
News" onClick="showNews()" />
This is simply because an XML start tag <xsl-value-of> cannot begin when a second start tag <input> has not been completed. Instead, the XSL element "attribute should be used":
<input type="button" onClick="showNews()" >
<xsl:attribute name="value">More <xsl:value-of
select="$country" /> News</xsl:attribute>
</input>
The remaining part that needs to be dynamically generated are:
"ex-President Jiang confirmed to love chocolate.",
"Primer Zhu's long lost pet found!",
"Shanghai endorses zoning.",
"Hong Kong ranks first in VSOP consumption."
The content of each Javascript's string can be obtained from the <headline> element with the following format:
"[content-of-<headline>]",
except for the last string, which should not end with a ",".
The XSLT code for this is relatively straightforward:
<xsl:for-each select="//headline">
"<xsl:value-of select="." />"
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
The new XSLT program looks like the following where changes are highlighted.
news3.xsl
<?xml version='1.0'?>
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="html" version="4.0"
indent="yes"
/>
<xsl:variable name="country">
<xsl:value-of select="//country" />
</xsl:variable>
<xsl:template match='/'>
<html>
<head>
<title><xsl:value-of select="$country" />
News</title>
<script language="Javascript">
<![CDATA[
<!-- Hide scripts from older browsers.
Function nextNews()
{ nextNews.count++;
if (nextNews.count >= nextNews.News.length)
{ nextNews.count = 0;
}
return nextNews.News[nextNews.count];
}
nextNews.News = new Array(
]]>
<xsl:for-each select="//headline">
"<xsl:value-of select="." />"
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
<![CDATA[
);
nextNews.count = nextNews.News.length-1;
function showNews() {
document.getElementById('news').innerHTML = nextNews();
}
// -->
]]>
</script>
</head>
<body style="background-color:#ccccff;font-family:verdana;font-size:10pt"
onLoad="showNews()">
<p>
<xsl:value-of select="$country" /> news:
</p>
<div id="news" style="background-color:#FEFFD9; width:400;"></div>
<p>
<form onSubmit="showNews(); return false; ">
<input type="button" onClick="showNews()" >
<xsl:attribute name="value">More <xsl:value-of select="$country"
/> News</xsl:attribute>
</input>
</form>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
This program will generate the output described in the problem specification. However, there are errors which will be corrected in the next subsection.
3.5 Target language consideration
Since XSLT may output many document formats, it is necessary to consider the
syntax and semantic of the target language. Using a typical sample for development
is a good starting point. However, the sample may not be good enough to test
all restrictions of the target language.
In our example, the followings are special cases that have not been handled by the XSLT program.
Case (1): If one of the news item is:
<entry num="_1">
<headline>Shanghai wins bid to host 2010 "World Expo"</headline>
<harvesttime>DEC 5 2002 9:08PM</harvesttime>
<url>http://www.chinaonline.com/</url>
</entry>
the generated dynamic HTML code contains a syntax error.
Case (2): If one of the news item is:
<entry num="_1">
<headline>Shanghai wins bid to host 2010\2011 World Expo</headline>
<harvesttime>DEC 5 2002 9:08PM</harvesttime>
<url>http://www.chinaonline.com/</url>
</entry>
the page displayed is not correct:

case (3): If one of the news item is:
<entry num="_1">
<headline>Shanghai wins bid to host 2010 <World>
<Expo></headline>
<harvesttime>DEC 5 2002 9:08PM</harvesttime>
<url>http://www.chinaonline.com/</url>
</entry>
the page displayed is not correct:

The reasons for these errors are related to special characters and syntax of the target language: HTML and Javascript. Both XSLT and the target output language syntax use special characters. Handling both kinds of special characters may make the code difficult to read and attention should always be paid.
In case (1), examination of the source code generated for the news entry:
"Shanghai wins bid to host 2010 "World Expo""
,
shows that the problem appears because '"' is a special charactes within a Javascript's string literal. It should be escapes as '\"':
"Shanghai wins bid to host 2010 \"World
Expo\""
,
Case (2) is similar. The source code generated is:
"Shanghai wins bid to host 2010\2011 World Expo"
,
The escape character "\" should itself be escaped as "\\":
"Shanghai wins bid to host 2010\\2011 World
Expo"
,
The first two cases are due to the requirements of Javascript's syntax. In case (3), since the news headline is output to a <div> element using the innerHTML property, it uses HTML syntax. The source code generated in this case is:
"Shanghai wins bid to host 2010 <World> <Expo>"
,
Since the browser does not understand the elements <World> and <Expo>, they are ignored and not displayed. To overcome this problem in HTML, the character "<" should use the entity "<". In a similar manner, "&" should also use "&".
Note that a good study of the context of the target language is necessary. For example, if the character '"' is used within Javascript's string literal, it should be converted to '\"' to satisfy Javascript syntax. On the other hand, if a '"' is generated as part of a HTML attribute value, it should be converted to '"a' to satisfy HTML syntax.
To correct these problems in our example, it is necessary to make the following substring replacements in order:
Note that the conversion order is important. (1) must be done before (2) and (3) must be done before (4).
Unfortunately, XPath and XSLT 1.0 do not support substring replacement and it is necessary to define your own templates for doing so.
(The closest 1.0 function is translate(value, string1, string2) which are used for character replacement. Every occurrence of each character in string1 in value is replaced by the corresponding character in string2. For example, translate('aabbcdd', 'abc', 'xyz') gives 'xxyyzdd'. XPath and XSLT 2.0 support substring replacement using pattern matching in a way similar to the s function in Perl [10].)
Fortunately, techniques for substring replacement are widely known for XSLT 1.0. For example, the following XSLT program converts all occurrences of "dog" to "cat" in text (but not attribute values) for any XML input document. It is based on various techniques discussed in the XSLT FAQ maintained by Dave Pawson [11].
dogTocat.xsl:
<?xml version='1.0'?>
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="xml" encoding="ISO-8859-1" indent="yes" standalone="yes"
/>
<xsl:template match='/'>
<xsl:apply-templates />
</xsl:template>
<xsl:template match='*'>
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match='text()'>
<xsl:call-template name="replace-string">
<xsl:with-param name="string"
><xsl:value-of select="." /></xsl:with-param>
<xsl:with-param name="replace"
select="'dog'" />
<xsl:with-param name="with"
select="'cat'" />
</xsl:call-template>
</xsl:template>
<xsl:template name="replace-string">
<xsl:param name="string" />
<xsl:param name="replace" />
<xsl:param name="with" />
<xsl:choose>
<xsl:when test="contains($string,$replace)">
<xsl:value-of select="substring-before($string,$replace)"
/>
<xsl:value-of select="$with" />
<xsl:call-template name="replace-string" >
<xsl:with-param name="string"
select="substring-after($string,$replace)" />
<xsl:with-param name="replace"
select="$replace" />
<xsl:with-param name="with"
select="$with" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
The essence of the program is in the template "replace-string" which
accepts three parameters 'string', 'replace' and 'with'. If the string is found
to contain 'replace', the substring before matching and the replacement string
'with' are returned. It is then followed by a recursive call to replace the
remaining of the input string.
Using the replace-string template, our final XSLT code is shown below. Changes are again highlighted.
news4.xsl:
<?xml version='1.0'?>
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="html" version="4.0"
indent="yes"
/>
<xsl:variable name="country">
<xsl:value-of select="//country" />
</xsl:variable>
<xsl:template match='/'>
<html>
<head>
<title><xsl:value-of select="$country" /> News</title>
<script language="Javascript">
<![CDATA[
<!-- Hide scripts from older browsers.
Function nextNews()
{ nextNews.count++;
if (nextNews.count >= nextNews.News.length)
{ nextNews.count = 0;
}
return nextNews.News[nextNews.count];
}
nextNews.News = new Array(
<xsl:for-each select="//headline">
<xsl:variable name="temp1">
<xsl:call-template name="replace-string" >
<xsl:with-param name="string" >
<xsl:call-template name="replace-string"
>
<xsl:with-param
name="string" ><xsl:value-of select="." /></xsl:with-param>
<xsl:with-param
name="replace" select="'\'" />
<xsl:with-param
name="with" select="'\\'" />
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="replace" select="'"'"
/>
<xsl:with-param name="with" select="'\"'"
/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="temp2">
<xsl:call-template name="replace-string" >
<xsl:with-param name="string" >
<xsl:call-template name="replace-string"
>
<xsl:with-param
name="string" ><xsl:value-of select="$temp1" /></xsl:with-param>
<xsl:with-param
name="replace" select="'&'" />
<xsl:with-param
name="with" select="'&amp;'" />
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="replace" select="'<'"
/>
<xsl:with-param name="with" select="'\&lt;'"
/>
</xsl:call-template>
</xsl:variable>
"<xsl:value-of select="$temp2" />"
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
<![CDATA[
);
nextNews.count = nextNews.News.length-1;
function showNews() {
document.getElementById('news').innerHTML = nextNews();
}
// -->
</script>
</head>
<body style="background-color:#ccccff;font-family:verdana;font-size:10pt"
onLoad="showNews()">
<p>
<xsl:value-of select="$country" /> news:
</p>
<div id="news" style="background-color:#FEFFD9; width:400;"></div>
<p>
<form onSubmit="showNews(); return false; ">
<input type="button" onClick="showNews()" >
<xsl:attribute name="value">More <xsl:value-of select="$country"
/> News</xsl:attribute>
</input>
</form>
</p>
</body>
</html>
</xsl:template>
<xsl:template name="replace-string">
<xsl:param name="string" />
<xsl:param name="replace" />
<xsl:param name="with" />
<xsl:choose>
<xsl:when test="contains($string,$replace)">
<xsl:value-of select="substring-before($string,$replace)"
/>
<xsl:value-of select="$with" />
<xsl:call-template name="replace-string" >
<xsl:with-param name="string"
select="substring-after($string,$replace)" />
<xsl:with-param name="replace"
select="$replace" />
<xsl:with-param name="with"
select="$with" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Note that two variables, temp1 and temp2, are used to hold the temporary results of substring replacements in two steps. The first step replaces '\' and '"' by '\\' an d'\"' respectively. The second step replaces '&' and '<' by '&' and '<'. It is also important to consider special characters in XSLT itself. For example, to convert '<' to '<', using the following code will create a syntax error:
...
<xsl:with-param name="replace" select="'<'" />
<xsl:with-param name="with" select="'<'" />
This is because < and & are special characters and entities must be used:
<xsl:with-param name="replace" select="'<'" />
<xsl:with-param name="with" select="'\&lt;'" />
4. Conclusions
XSLT is a powerful language for transforming XML to create documents/programs of your choice languages. This article presents guidelines for effective dynamic generation of generating dynamic HTML using XSLT by working through detailed development steps in a realistic example.
References
[1] W3C's XSL and XSLT page: http://www.w3.org/Style/XSL/.
[2] Sun's Java Server Page (JSP) page: http://java.sun.com/products/jsp/.
[3] Microsoft, Getting Started With Active Server Pages, http://support.microsoft.com/default.aspx?scid=kb;en-us;q297943.
[4] Microsoft's ASP.Net home page: http://www.asp.net/.
[5] W3C's DOM page: http://www.w3.org/DOM/.
[6] W3C XSLT 1.0 Recommendation: http://www.w3.org/TR/xslt.
[7] W3C XSLT 2.0 Working Draft: http://www.w3.org/TR/xslt20/.
[8] Sun's XML Technologies front page: http://java.sun.com/xml/.
[9] W3C XPath 1.0 Recommendation: http://www.w3.org/TR/xpath.
[10] W3C XQuery 1.0 and XPath 2.0 Functions and Operators Working Draft: http://www.w3.org/TR/xquery-operators/.
[11] Dave Pawson, XSLT FAQ on XSLT: http://www.dpawson.co.uk/xsl/sect2/N7240.html
Dr. Kwok-Bun Yue
Professor, Computer Science and Computer Information Systems
Chair, Division of Computing and Mathematics
University of Houston-Clear Lake
2700 Bay Area Boulevard
Houston, TX 77058
Yue's home page
yue@uhcl.edu
281-283-3864