Tip: Outputting HTML from an XSL style sheet

Resolving differences between HTML and XML

Because HTML is so similar to XML, it should be fairly straightforward to create an XSLT style sheet that outputs HTML. Unfortunately, the differences between HTML and XML that do exist can cause pages to be displayed incorrectly in older browsers. This tip discusses those differences, and explains how to use XSLT's output element to resolve the issues they create.

Nicholas Chase (nicholas@nicholaschase.com), President, Chase and Chase, Inc.

Nicholas Chase has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, and an Oracle instructor. More recently, he was the Chief Technology Officer of Site Dynamics Interactive Communications in Clearwater, Fla., and is the author of three books on Web development, including Java and XML From Scratch (Que) and the upcoming Primer Plus XML Programming (Sams). He loves to hear from readers and can be reached at nicholas@nicholaschase.com.



01 May 2002

Also available in Japanese

For the purpose of this tip, I'll take an XML file of potential user choices for an opt-in list and convert it into a form. This form has checkboxes, some of which are checked by default, and uses JavaScript to confirm that the submission deadline hasn't passed before the form is submitted:

Listing 1. The source file
<?xml version="1.0"?>
<choices>
   <option default="no">
       <value>1</value><genre>Drama</genre>
   </option>
   <option default="yes">
       <value>2</value><genre>Comedy</genre>
   </option>
   <option default="yes">;
       <value>3</value><genre>Science Fiction</genre>
   </option>
   <option default="no">
       <value>4</value><genre>Romance</genre>
   </option>
   <option default="yes">
       <value>5</value><genre>Adventure</genre>
   </option>
</choices>

The target file is a simple form that executes a script to determine whether to submit the form:

Listing 2. The target file
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Select Choices</title>
<script version="1.3" type="text/javascript">

function checkDate() {
   var today = new Date();
   var deadlineDate = new Date('3/3/2002');
   if (today > deadlineDate) {
        alert('The deadline has passed.');
        return false;
   } else {
        return true;
   }   
}
</script>
</head>
<body>

<form onsubmit="return checkDate()" method="post" action="processform.jsp">
<p>We will send you information on the subjects in which you're
interested. Please check all that apply.</p>
   
<input type="checkbox" value="1">Drama<br>
<input type="checkbox" value="2" checked>Comedy<br>
<input type="checkbox" value="3" checked>Science Fiction<br>
<input type="checkbox" value="4">Romance<br>
<input type="checkbox" value="5" checked>Adventure<br>
<input value="Submit Choices" type="submit">
</form>

</body>
</html>

The style sheet

You may notice that the target file is not a well-formed XML document. Specifically, HTML allows you to leave out certain end-tags (such as input and br) and to minimize certain attribute values that are evaluated based on their presence, such as checked. Notice also the greater-than sign (>) in the checkDate() function.

The style sheet must take all of this into account, and make adjustments accordingly:

Listing 3. The style sheet
<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0">

<xsl:template match="/choices">
<html><head><title>Select Choices</title>

<script type="text/javascript" version="1.3">

function checkDate() {
   var today = new Date();
   var deadlineDate = new Date('3/3/2002');
   if (today > deadlineDate) {
        alert('The deadline has passed.');
        return false;
   } else {
        return true;
   }   
}
</script>

</head>
<body>
<form action="processform.jsp" method="post" onsubmit="return checkDate()">
<p>We will send you information on the subjects in which you're
interested. Please check all that apply.</p>
	<xsl:apply-templates/>
<input type="submit" value="Submit Choices"/>
</form>
</body>
</html>
</xsl:template>

<xsl:template match="option">
    <xsl:element name="input">
        <xsl:attribute name="type">checkbox</xsl:attribute>
        <xsl:attribute name="value"><xsl:value-of select="value"/>
        </xsl:attribute>
        <xsl:if test="@default='yes'">
            <xsl:attribute name="checked">checked</xsl:attribute>
        </xsl:if>
    </xsl:element>
    <xsl:value-of select="genre"/>
    <br />    
</xsl:template>

</xsl:stylesheet>

The style sheet itself is fairly straightforward. The root element template displays the main structure of the page, with a separate template for each choice that creates an input element. This element carries the value as an attribute (and, potentially, the checked attribute), and displays the choice itself and a <br /> tag.

Unfortunately, if this style sheet were processed as XML, these accommodations would carry through to the final document:

Listing 4. The results as XML
<?xml version="1.0" encoding="UTF-8"?>
<html><head><title>Select Choices</title>
<script version="1.3" type="text/javascript">

function checkDate() {
   var today = new Date();
   var deadlineDate = new Date('3/3/2002');
   if (today > deadlineDate) {
        alert('The deadline has passed.');
        return false;
   } else {
        return true;
   }   
}
</script></head><body>
    <form onsubmit="return checkDate()" method="post" action="processform.jsp">
<p>We will send you information on the subjects in which you're
interested. Please check all that apply.</p>
   <input type="checkbox" value="1"/>Drama<br/>
   <input type="checkbox" value="2" checked="checked"/>Comedy<br/>
   <input type="checkbox" value="3" checked="checked"/>Science Fiction<br/>
   <input type="checkbox" value="4"/>Romance<br/>
   <input type="checkbox" value="5" checked="checked"/>Adventure<br/>
<input value="Submit Choices" type="submit"/></form></body></html>

Before going on, let me acknowledge that the output above is valid XHTML, in that all of the tags are existing XHTML tags, it's well-formed, and so on (XHTML is simply HTML 4.01 reformulated as XML). Aside from the fact that white space can make this difficult to read, many older browsers do not interpret this page correctly because of the closing slashes in the empty tags. (Normally, developers simply add a space before the closing slash to prevent problems, but the processor doesn't know that.)

What's more, the script does not execute correctly because the greater-than sign is still represented as an entity (>).


The output method

Fortunately, the designers of XSLT anticipated this problem and added the output element. For example, to specify that you want the output document to be HTML, add the output method to the style sheet:

Listing 5. Add the output method
<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0">

<xsl:output method="html" indent="yes" version="4.0"/>

<xsl:template match="/choices">
...

The method attribute can take one of three values: xml, html, or text.

By using html as the output method, you tell the processor to do several things, including the following:

  • For script and style elements, replace any escaped characters (such as & and >) with their actual values (& and >, respectively).
  • For attributes, replace any occurrences of > with >.
  • Write empty elements such as <br>, <img>, and <input> without closing tags or slashes.
  • Write attributes that convey information by their presence as opposed to their value, such as checked and selected, in minimized form.

The end result is an HTML document that any browser should be able to handle.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into XML on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML
ArticleID=12105
ArticleTitle=Tip: Outputting HTML from an XSL style sheet
publish-date=05012002