An XSL style sheet can generate two types of errors: parse errors and run-time errors. There are ways to check for these errors and report them.
Here is a simple HTML page that uses XML data islands to load an XML file and an XSL style sheet and display the results.
<HTML>
<XML id="source" src="simple.xml"></XML>
<XML id="style" src="simple.xsl"></XML>
<SCRIPT event="onload" for="window">
showResult.innerHTML = source.transformNode(style.XMLDocument);
</SCRIPT>
<BODY>
<DIV id="showResult"></DIV>
</BODY>
</HTML>
The call to transformNode invokes the XSL processor, and the resulting HTML is inserted into the page. But what if nothing appears? An error occurred somewhere, so you need to check to see where it happened.
The parseError object should first be checked to see whether there was a parsing error in the XML file or in the style sheet. Parsing errors on data islands do not generate error messages in the browser. If an error occurred, you can retrieve the cause and try to recover gracefully, or put an error message into the page so you can see what went wrong. In the following example, parsing errors are checked for; if they occur, a function is called to format the error information in a fashion appropriate for inserting into the HTML document.
<HTML>
<HEAD>
<TITLE>Simple Error Message Demo</TITLE>
</HEAD>
<XML id="source" src="review.xml"></XML>
<XML id="style" src="review.xsl"></XML>
<SCRIPT src="reportErrors.js"></SCRIPT>
<SCRIPT event="onload" for="window">
if (source.parseError.errorCode != 0)
result = reportParseError(source.parseError);
else
{
if (style.parseError.errorCode != 0)
result = reportParseError(style.parseError);
else
{
try {
result = source.transformNode(style.XMLDocument);
}
catch (exception) {
result = reportRuntimeError(exception);
}
}
}
// insert the results into the page
showResult.innerHTML = result;
</SCRIPT>
<BODY>
<DIV id="showResult"></DIV>
</BODY>
</HTML>
Besides parsing errors, the above example also detects XSL run-time errors (those occurring inside calls to transformNode). Run-time errors will normally be reported to the user through the standard Microsoft® Internet Explorer 5 error dialog box. However, it is often useful to suppress this dialog box and do your own handling of the error message. The JScript® (compatible with ECMA 262 language specification) 5.0 try and catch functions allow the error to be suppressed and handled consistently with parsing errors.
The actual formatting of the error information in the above example is provided by two functions: reportParseError and reportRuntimeError, which reside in a separate script file, reportErrors.js. The main HTML page references this script file.
// Parse error formatting function
function reportParseError(error)
{
var s = "";
for (var i=1; i<error.linepos; i++) {
s += " ";
}
r = "<font face=Verdana size=2><font size=4>XML Error loading '" +
error.url + "'</font>" +
"<P><B>" + error.reason +
"</B></P></font>";
if (error.line > 0)
r += "<font size=3><XMP>" +
"at line " + error.line + ", character " + error.linepos +
"\n" + error.srcText +
"\n" + s + "^" +
"</XMP></font>";
return r;
}
// Runtime error formatting function
function reportRuntimeError(exception)
{
return "<font face=Verdana size=2><font size=4>XSL Runtime Error</font>" +
"<P><B>" + exception.description + "</B></P></font>";
}
These two functions return HTML fragments that can be inserted into the HTML page in place of the correct transformation result, alerting you of a problem and assisting you in correcting it.
Reporting an error using this mechanism is also useful in an ASP page. Here is the equivalent code for processing an XML file on the server.
<%@ LANGUAGE = JScript %>
<%
// Parse error formatting function
function reportParseError(error)
{
var s = "";
for (var i=1; i<error.linepos; i++) {
s += " ";
}
r = "<font face=Verdana size=2><font size=4>XML Error loading '" +
error.url + "'</font>" +
"<P><B>" + error.reason +
"</B></P></font>";
if (error.line > 0)
r += "<font size=3><XMP>" +
"at line " + error.line + ", character " + error.linepos +
"\n" + error.srcText +
"\n" + s + "^" +
"</XMP></font>";
return r;
}
// Run-time error formatting function
function reportRuntimeError(exception)
{
return "<font face=Verdana size=2><font size=4>XSL Runtime Error</font>" +
"<P><B>" + exception.description + "</B></P></font>";
}
// Set the source and style sheet locations here
var sourceFile = Server.MapPath("review.xml");
var styleFile = Server.MapPath("review-simple.xsl");
// Load the XML
var source = Server.CreateObject("Microsoft.XMLDOM");
source.async = false;
source.load(sourceFile);
// Load the XSL
var style = Server.CreateObject("Microsoft.XMLDOM");
style.async = false;
style.load(styleFile);
if (source.parseError.errorCode != 0)
result = reportParseError(source.parseError);
else
{
if (style.parseError.errorCode != 0)
result = reportParseError(style.parseError);
else
{
try {
result = source.transformNode(style);
}
catch (exception) {
result = reportRuntimeError(exception);
}
}
}
Response.Write(result);
%>
The code here is essentially the same as that for the client side, with the same error formatting functions and processing. The Server.CreateObject and Response.Write methods are used in place of the client-side functions provided by data islands and the innerHTML method.