Converting XML To HTML Using ColdFusion And XSLT

Posted September 11, 2007 at 2:12 PM by Ben Nadel

Tags: ColdFusion

As part of my exploration of XML, I've been playing around more with ColdFusion and XSLT. For this experiment, I am trying to encapsulate the data of an HTML page in XML. Then, I am using ColdFusion and XSLT to transform that XML document into an XHTML page. The ColdFusion XML document that I am starting off with contains:

  • Page Title
  • Meta Data information
  • Navigation elements
  • Primary Content information

Here is my ColdFusion XML document, built using the CFXML tag:

  • <!---
  • Define the ColdFusion XML document object that
  • will represent the data on an HTML page.
  • --->
  • <cfxml variable="xmlPage">
  •  
  • <page>
  • <title>
  • Maria Bello Fan Site
  • </title>
  •  
  • <!--- Meta information. --->
  • <meta>
  • <keywords>
  • maria bello,sexy girls,crazy sexy
  • </keywords>
  • <description>
  • My Maria Bello fan site.
  • </description>
  • </meta>
  •  
  • <!--- Primary navigation. --->
  • <primarynav>
  • <navitem
  • text="Home"
  • href="index.cfm"
  • ison="true"
  • />
  • <navitem
  • text="Photos"
  • href="photos.cfm"
  • />
  • <navitem
  • text="Videos"
  • href="videos.cfm"
  • />
  • </primarynav>
  •  
  • <!---
  • Primary page content. This will make up the bulk
  • of the rendered page.
  • --->
  • <primarycontent>
  • <![CDATA[
  • <p>
  • Welcome to my Maria Bello Fan Site. If you
  • are like me, then you think she's just all
  • kinds of sexy. I've spent many hours
  • compiling this repository of images and
  • videos for your (and my) enjoyment. Hope you
  • enjoy and please check back soon.
  • </p>
  •  
  • <p>
  • If Maria Bello were a cereal, she'd be
  • magically babelicious.
  • </p>
  • ]]>
  • </primarycontent>
  • </page>
  •  
  • </cfxml>

You will notice that I am keeping a lot of white space in my XML nodes (ex. keywords and description nodes). This is NOT recommended. This adds white space to the final XML node value. I am doing this purely for better code display, not as a best practice. Notice also that the primary content of the page is contained in a CDATA node. From what I have read about XSLT in general, it would appear that CDATA node type is not well liked (and perhaps not widely supported???); however, it seems to work quite nicely for XHTML type pages.

Then, once I have my ColdFusion XML document ready, I need to create my XSLT templates. These are the XML directives that will take the ColdFusion XML document and translate it in a divide-and-conquer fashion into the resultant data file which is, in our case, an XHTML page.

  • <!--- Define the XSL Transformation (XSLT). --->
  • <cfsavecontent variable="strXSLT">
  •  
  • <!--- Document type declaration. --->
  • <?xml version="1.0" encoding="ISO-8859-1"?>
  •  
  • <xsl:transform
  • version="1.0"
  • xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  •  
  • <!---
  • Tell the ColdFusion XSLT engine that we are
  • going to be producing an HTML document and that we
  • want to use indenting.
  • --->
  • <xsl:output
  • method="html"
  • indent="yes"
  • />
  •  
  • <!---
  • Bind this template to the root of the XML document
  • using the "/" match attribute.
  • --->
  • <xsl:template match="/">
  •  
  • <html>
  • <head>
  • <title>
  • <!--- Output the page title. --->
  • <xsl:value-of select="page/title" />
  • </title>
  •  
  • <!--- Output meta data template. --->
  • <xsl:apply-templates select="page/meta" />
  • </head>
  • <body>
  •  
  • <h1>
  • <xsl:value-of select="page/title" />
  • </h1>
  •  
  • <!--- Output primary navigation. --->
  • <xsl:apply-templates select="//primarynav" />
  •  
  • <!--- Output page content. --->
  • <xsl:apply-templates
  • select="page/primarycontent"
  • />
  •  
  • </body>
  • </html>
  •  
  • </xsl:template>
  •  
  •  
  • <!--- Template for HTLM meta data. --->
  • <xsl:template match="meta">
  •  
  • <!--- Output met akeywords element. --->
  • <xsl:element name="meta">
  • <xsl:attribute name="keywords">
  • <xsl:value-of select="keywords" />
  • </xsl:attribute>
  • </xsl:element>
  •  
  • <!--- Output meta description element. --->
  • <xsl:element name="meta">
  • <xsl:attribute name="description">
  • <xsl:value-of select="description" />
  • </xsl:attribute>
  • </xsl:element>
  •  
  • </xsl:template>
  •  
  •  
  • <!--- Template for the primary navigation items. --->
  • <xsl:template match="primarynav">
  •  
  • <ul id="primarynav">
  • <!--- Loop over nav items. --->
  • <xsl:for-each select="navitem">
  •  
  • <li>
  • <!--- Define the nav link HTML. --->
  • <xsl:element name="a">
  • <xsl:attribute name="href">
  • <xsl:value-of select="@href" />
  • </xsl:attribute>
  •  
  • <!---
  • Check to see if this link is on.
  • If so, then we have to add the
  • appropriate class.
  • --->
  • <xsl:if test="@ison = 'true'">
  • <xsl:attribute name="class">
  • on
  • </xsl:attribute>
  • </xsl:if>
  •  
  • <!--- Text of link. --->
  • <xsl:value-of select="@text" />
  • </xsl:element>
  • </li>
  •  
  • </xsl:for-each>
  • </ul>
  •  
  • </xsl:template>
  •  
  •  
  • <!--- Template for primary page content. --->
  • <xsl:template match="primarycontent">
  •  
  • <div id="sitecontent">
  •  
  • <!---
  • When outputting the page's primary content,
  • make sure to DISABLE escaping so that our
  • XHTML will come through properly.
  • --->
  • <xsl:value-of
  • select="."
  • disable-output-escaping="yes"
  • />
  •  
  • </div>
  •  
  • </xsl:template>
  •  
  • </xsl:transform>
  •  
  • </cfsavecontent>
  •  
  •  
  • <!---
  • Output the transformed XML page data into an
  • HTML formatted web page using XSLT.
  • --->
  • #XmlTransform(
  • xmlPage,
  • Trim( strXSLT )
  • )#

I have chosen to make this ColdFusion XML Transformation a bit more complicated than it needs to be for the purposes of forcing myself to learn more about the XSLT syntax. Some of this complexity is self-imposed, but also, XSLT is just a complicated syntax. For instance, instead of just writing an XHTML element and using some conditional logic to write attributes (such as adding an "active" class to an "on" navigational item), you have to use the xsl:element node and add each attribute as a descendent xsl:attribute node. A bit wordy if you ask me.

Also, notice that when I am outputting the CDATA, I am using the xsl:value-of attribute, disable-output-escaping. I have to do this other wise the XSLT engine will convert the HTML elements into escaped HTML elements.

Running the above code, we get the following page:


 
 
 

 
Convertted XML To XHTML Using ColdFusion And XSLT  
 
 
 

XSLT is interesting. I think I am a little turned off by how complicated it seems to be. On the one hand, I like that you can take XML and convert it to any other kind of text-based data based on the Transformation files. But on the other hand, I feel like you can use ColdFusion to do this programmatically with much less stress. Plus, I think white space management is a big issue in XSLT. I like being able to space my ColdFusion code out in a way that makes me happy and produce quality output. I think that with XSLT, this is going to be a much harder task to accomplish.

Still not sure how I feel about it. I am gonna keep poking around; XSLT is HUGE! There are many functions and elements to be used. Luckily, it looks like ColdFusion only supports a subset of this functionality, so it won't be the beast that it could be. Plus, I am not sure I need to fully learn the syntax to get an idea of what is capable. The good thing is that it keeps me fresh with the XPath stuff I did a while back.




Reader Comments

Sep 11, 2007 at 2:29 PM // reply »
42 Comments

XSLT does have the ability to strip/preserve white-space. I haven't tested Coldfusion's implementation on this, but it is available:

http://www.cafeconleche.org/books/bible2/chapters/ch17.html#d1e8886


Sep 11, 2007 at 2:53 PM // reply »
10,640 Comments

@Dustin,

You maginificent bastard! That works (the normalize-space function). I had tried to use xsl:strip-space but couldn't get it to work. Maybe I wasn't doing it right it just wasn't supported in ColdFusion. Nicely done!


Sep 11, 2007 at 2:58 PM // reply »
42 Comments

No problem!

The xsl:strip-space is to remove empty nodes from your XML so they don't display the whitespace of the empty node. The function name is a little misleading, I know for sure I was confused by it when I started using XSLT. From the link above:

"You can also automatically delete white-space only nodes in the input document by using xsl:strip-space."

w00t!


Jan 29, 2008 at 7:56 PM // reply »
1 Comments

Yes, I agree. We just got the Google Mini, which comes with built-in xslt, which you can edit. It just seemed so much easier to return the results in XML, convert them to a query, and then manipulate them through ColdFusion.

This post helped reaffirm my decision.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Feb 10, 2012 at 7:21 PM
jQuery AJAX Strips Script Tags And Inserts Them After Parent-Most Elements
Update! Instead of $(eval(options.insertAfter)).after(data['insertData']); I now use: var ajaxNode = document.createElement('span'); var parent = $(eval(options.insertAfter))[0].parentNode; ... read »
Feb 10, 2012 at 6:18 PM
jQuery AJAX Strips Script Tags And Inserts Them After Parent-Most Elements
encountered this same, what I consider, jQuery bug last week. I'm building a site in which I load some content via AJAX. This content contains Linkedin share button placeholders which Linkedin API ne ... read »
Feb 10, 2012 at 11:30 AM
Cross-Origin Resource Sharing (CORS) AJAX Requests Between jQuery And Node.js
After you understand the concepts here, this is an awesome cheatsheet for enabling CORS in just about anything http://enable-cors.org/ ... read »
JM
Feb 10, 2012 at 9:10 AM
My Safari Browser SQLite Database Hello World Example
@Amy, Here is a very good tutorial on how to use JOIN: http://www.sqltutorial.org/sqljoin-innerjoin.aspx ... read »
Feb 10, 2012 at 4:42 AM
Building A Twitter-Inspired RESTful API Architecture In ColdFusion
This is great, very useful Ben. I spotted a small typo in the api.cgm listing: <cfthrow type="Unauthroized" /> Cheers Stefan ... read »
Feb 9, 2012 at 10:35 PM
CFDirectory Filtering Uses Pipe Character For Multiple Filters (Thanks Steve Withington)
I was wondering if there would be a filter you could apply so that you got everything but what you included in the filter. As in show me all docs that are not a .pdf. ... read »
Feb 9, 2012 at 10:29 PM
Learning ColdFusion 9: Application-Specific Data Sources
@Ben, No offence, but if people were really wanting advanced features they would be using a platform like ASP.NET MVC. CFML is so structurally compromised as a tag-based scripting language that ... read »
Feb 9, 2012 at 10:03 PM
Subversion - Cleanup Failed To Process The Following Paths
@Leviaguirre, do you still have problems with this? ... read »