Convert jQuery XML Documentation To HTML / PDF Using ColdFusion And XSLT

Posted September 20, 2007 at 9:02 AM

Tags: ColdFusion

A long time ago, I took the jQuery documentation XML off of www.visualjquery.com and converted it into a PDF using a lot of ColdFusion XmlSearch() calls and a ton of ArrayLen() logic. It ended up being a lot of code. Well, now that I have been doing a lot of learning about XSLT in ColdFusion, I thought it would be fun to redo the task using XSL transformations rather than ColdFusion logic.

It turns out, the ColdFusion and XSLT approach is sooo much easier. There's a lot less conditional logic and I think the code just looks a heck of a lot cleaner. I am still not sure where the balance is between using xsl:template vs. using xsl:for-each. At times, they seem to do the same thing so I'm not sure if there is a best practice as to which one to use.

Before we get into the code, you can check out the links below to see this in action:

Convert jQuery XML to XHTML

Convert jQuery XML to XHTML to PDF

I couldn't find the jQuery 1.2 XML documentation, so for this test, I just used the older jQuery 1.1 documentation. Hopefully the format of the XML has not changed and this algorithm should be applicable to the newest documentation as well.

 Launch code in new window » Download code as text file »

  • <!---
  • Read in the jquery XML documentation. Unfortunately, I
  • had a real hard time trying to find the most up-to-date
  • XML docs, so I had to go with the quite outdated 1.1.
  • --->
  • <cffile
  • action="read"
  • file="#ExpandPath( './jquery-1.1.xml' )#"
  • variable="xmlDocumentation"
  • />
  •  
  •  
  • <!---
  • Create the XSLT document that will transform out jQuery
  • XML into an XHTML web page.
  • --->
  • <cfxml variable="xmlTransform">
  •  
  • <!--- 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">
  •  
  • <xsl:output
  • omit-xml-declaration="yes"
  • method="xml"
  • version="1.0"
  • encoding="UTF-8"
  • doctype-public="-//W3C//DTD XHTML 1.1//EN"
  • doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
  • indent="yes"
  • />
  •  
  •  
  • <!--- Match the root-level node. --->
  • <xsl:template match="/">
  •  
  • <html>
  • <head>
  • <title>jQuery Documentation</title>
  • <cfinclude template="jquery_stylesheet.txt" />
  • </head>
  • <body>
  •  
  • <h1>
  • jQuery 1.1 Documentation
  • </h1>
  •  
  • <!---
  • Apply templates to direct descendents of the
  • root node (should be the CAT nodes).
  • --->
  • <xsl:apply-templates />
  •  
  • </body>
  • </html>
  •  
  • </xsl:template>
  •  
  •  
  • <xsl:template match="cat">
  •  
  • <h2>
  • <!---
  • Check to see if this category is a
  • sub-category. If so, we have to add the
  • conditional class attribute.
  • --->
  • <xsl:if test="../../cat">
  • <xsl:attribute name="class">
  • <xsl:text>sub</xsl:text>
  • </xsl:attribute>
  • </xsl:if>
  •  
  • <xsl:value-of select="@value" />
  • </h2>
  •  
  • <!---
  • Apply templates to all direct descendents of the
  • current category node.
  • --->
  • <xsl:apply-templates />
  •  
  • </xsl:template>
  •  
  •  
  • <xsl:template match="method">
  •  
  • <h3>
  • <xsl:value-of select="@name" />
  •  
  • <!--- Output the named params. --->
  • <span class="params">
  • <xsl:text>( </xsl:text>
  • <xsl:for-each select="params">
  •  
  • <xsl:value-of select="@name" />
  • <xsl:if test="position() != last()">
  • <xsl:text>, </xsl:text>
  • </xsl:if>
  •  
  • </xsl:for-each>
  • <xsl:text> )</xsl:text>
  • </span>
  • </h3>
  •  
  • <div class="methodbody">
  •  
  • <xsl:apply-templates select="desc" />
  •  
  • <xsl:if test="params">
  •  
  • <h4>
  • <xsl:text>Parameterss</xsl:text>
  • </h4>
  •  
  • <xsl:apply-templates select="params" />
  •  
  • </xsl:if>
  •  
  • <xsl:if test="options">
  •  
  • <h4>
  • <xsl:text>Hash Options</xsl:text>
  • </h4>
  •  
  • <xsl:apply-templates select="options" />
  •  
  • </xsl:if>
  •  
  • <xsl:if test="@type">
  •  
  • <h4>
  • <xsl:text>Returns</xsl:text>
  • </h4>
  •  
  • <p>
  • <xsl:value-of select="@type" />
  • </p>
  •  
  • </xsl:if>
  •  
  • <xsl:apply-templates select="examples" />
  •  
  • <xsl:if test="see">
  •  
  • <h4>
  • <xsl:text>See Also</xsl:text>
  • </h4>
  •  
  • <p>
  • <xsl:for-each select="see">
  • <xsl:value-of select="." />
  • <br />
  • </xsl:for-each>
  • </p>
  •  
  • </xsl:if>
  •  
  • </div>
  •  
  • </xsl:template>
  •  
  •  
  • <!---
  • This template will match params or options
  • which are formatted in the same way.
  • --->
  • <xsl:template match="params|options">
  •  
  • <p>
  • <xsl:if test="@name != ''">
  • <strong>
  • <xsl:value-of select="@name" />
  • </strong>
  • <xsl:text>: </xsl:text>
  • </xsl:if>
  •  
  • <xsl:if test="@type != ''">
  • <em>
  • <xsl:value-of select="@type" />
  • </em>
  • <xsl:text>: </xsl:text>
  • </xsl:if>
  •  
  • <xsl:value-of select="." />
  • </p>
  •  
  • </xsl:template>
  •  
  •  
  • <xsl:template match="desc">
  •  
  • <p class="description">
  • <xsl:value-of select="." />
  • </p>
  •  
  • </xsl:template>
  •  
  •  
  • <xsl:template match="examples">
  •  
  • <h4>
  • <xsl:text>Example</xsl:text>
  • </h4>
  •  
  • <xsl:if test="desc">
  • <p>
  • <xsl:value-of select="desc" />
  • </p>
  • </xsl:if>
  •  
  • <xsl:if test="code">
  • <p>
  • <xsl:value-of select="code" />
  • </p>
  • </xsl:if>
  •  
  • <xsl:if test="before">
  • <h5>
  • <xsl:text>Before</xsl:text>
  • </h5>
  •  
  • <p>
  • <xsl:value-of select="before" />
  • </p>
  • </xsl:if>
  •  
  • <xsl:if test="result">
  • <h5>
  • <xsl:text>Result</xsl:text>
  • </h5>
  •  
  • <p>
  • <xsl:value-of select="result" />
  • </p>
  • </xsl:if>
  •  
  • </xsl:template>
  •  
  • </xsl:transform>
  •  
  • </cfxml>
  •  
  •  
  • <!--- Output the jQuery XML documention transformation. --->
  • <cfset WriteOutput(
  • XmlTransform(
  • xmlDocumentation,
  • xmlTransform
  • )
  • ) />

The above code takes the XML and transforms it using ColdFusion's XmlTransform() to convert it into an XHTML document. Notice that I am using the xsl:text element around some text literals (ex. h3, h4, h5). This is not required. I am doing this because by using the xsl:text element, the ColdFusion transformation engine reduces the amount of white space that it puts into the resultant XHTML. Minor note, but I thought I would point it out.

Now, we can take that one step further (as I did in my first attempt) and convert that into a PDF using a very simple CFDocument call:

 Launch code in new window » Download code as text file »

  • <!--- Create a PDF of the parse jQuery documentation. --->
  • <cfdocument
  • format="PDF"
  • pagetype="letter"
  • orientation="portrait"
  • unit="in"
  • encryption="none"
  • fontembed="Yes"
  • backgroundvisible="No">
  •  
  • <!--- Include the parsed jQuery XML. --->
  • <cfinclude template="./index.cfm" />
  •  
  • </cfdocument>

This XSLT stuff is really growing on me.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page





Reader Comments

Sep 20, 2007 at 10:06 AM // reply »
26 Comments

Keep it up! Another thorough, real-world example.

Though I haven't done a ton of XSLT, in the real-world work I've done with it, using XmlTransform with XSLT has always out-performed nasty structure and array looping, etc. Do you find the same to be true with the performance of ths XSLT example vs. the original?


Sep 20, 2007 at 10:34 AM // reply »
6,371 Comments

@Aaron,

It was definitely easier to code, which was cool. As a matter of processing performance, both work super fast. Although it would be curious to run it a bunch of times. Let me see what kind of comparison I can come up with.


Post Comment  |  Ask Ben

Recent Blog Comments
Jill
Nov 7, 2009 at 11:40 AM
How To Unformat Your Code (Like A Pro)
Derek, I think you might be right - sweet! Thanks for the link :) ... read »
Nov 7, 2009 at 11:25 AM
How To Unformat Your Code (Like A Pro)
I think it would be way easier to just use this http://www.logichammer.com/html-formatter/ He just released v3 and it rocks. ... read »
Jill
Nov 7, 2009 at 7:58 AM
How To Unformat Your Code (Like A Pro)
LMAO - this was pretty funny! I have to admit - I also love to reformat code so I can read it. My boss used to tell me to leave my OCD at home. Now I don't feel so bad after reading everyone else' ... read »
Nov 6, 2009 at 10:10 PM
How To Unformat Your Code (Like A Pro)
The timing of this post is just uncanny. I spent the last 15-20 minutes manually un-formatting my "Ben Nadel" style code within a CFC of mine. I was really digging the readability a few weeks ago, bu ... read »
Roe
Nov 6, 2009 at 5:11 PM
Passing Arrays By Reference In ColdFusion - SWEEET!
ArraySort also reorders the results of these java obj's ... read »
Nov 6, 2009 at 4:53 PM
How To Unformat Your Code (Like A Pro)
I tried to go *back* the other way. Adding formatting is actually a much more complicated problem than removing formatting. Anyway, here is what I could put together with a minimal amount of time: ... read »
Asaf
Nov 6, 2009 at 2:35 PM
ColdFusion GetPageContext() Massive Exploration
Hi, I actually found this post useful. I recently acquired a SSL certificate for my website and when I switched over to HTTPS Internet Explorer would throw an error when trying to download a dynamic ... read »
Nov 6, 2009 at 2:19 PM
How To Unformat Your Code (Like A Pro)
@Chuck, @Nathan, Well, now I feel like it's a challenge.... I accept. ... read »