Welcome!

ColdFusion Authors: Maureen O'Gara, Hovhannes Avoyan, Yakov Fain, Pat Romanski, Liz McMillan

Related Topics: ColdFusion

ColdFusion: Article

Transforming XML Part 3

Transforming XML Part 3

There once was a mild-mannered XML packet with greater ambitions. One day I'll be presentable, it thought! I'll dress up as HTML - and as WML, and maybe, just maybe, I can turn into WDDX!

Transformation looked scary, though, with lots of downloads, and installation, and really complicated syntax. But then along came ColdFusion MX, and the XML packet found that transformation wasn't such a big deal after all.

This is the third and final article in a series about ColdFusion MX and its new XML development tools. In previous CFDJ articles I focused on parsing XML and creating XML files (Vol. 4, issues 6 and 7, respectively). In this last article I'll describe how CFMX supports Extensible Stylesheet Language Transformations as a native technology.

XSLT is one of three major XML technologies that have driven adoption of XML as a data exchange format. (The others are DOM [Document Object Model] and SAX [Simple API for XML]). XSLT has been implemented for many platforms. There are XSLT processors built as COM objects (Microsoft's XML Core Services), and as libraries for C++, Perl, and Java developers (Apache's Xalan). XSLT processing is also built into the most recent browsers (Internet Explorer 6.0 and Netscape 6.2).

ColdFusion developers were able to use XSLT prior to the release of CFMX, but we had to locate and install the processors and learn the transformation syntax. CFMX now supports native XSLT with an embedded copy of Apache's Xalan processor (the Java version), and the whole thing just got much easier.

The XMLTransform() Function
An XSLT file is an XML file written in the XSLT language. To transform, you pass two packets into an XSLT processor. The first is the XML data packet; the second, the XSLT transformation packet. The processor performs the transformation and returns the resulting transformed text (see Figure 1).

CFMX executes transformations with the new XMLTransform() function. To perform a transformation, first read the contents of the XML and XSLT packets into ColdFusion text variables. Then pass the text variables into XMLTransform(), which returns the transformed text:

<CFSet myResult=XMLTransform(myXML, myXSLT)>

That's all there is to learn on the ColdFusion side. XMLTransform() passes the contents of the two packets into the XSLT processor and you get back the result. Everything you really need to learn is in the XSLT language itself.

How XSLT Works
XSLT provides a simple, extensible markup syntax for transforming XML into a variety of text formats. It can create formatted output as HTML or nonmarkup text, or transform from one flavor of XML to another. It's similar to CFML in that it's both a markup language and a command language.

XSLT is an XML-based language, and must follow the rules of well-formed XML. The root element is always the same:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
... transformation templates ...
</xsl:stylesheet>
The version number is always 1.0. The namespace URI indicates that the stylesheet follows the rules of the W3C's XSLT Recommendation, which was published in November 1999. The "xsl" namespace prefix is arbitrary, but all XSLT documents use it by convention. All XSLT command elements also have the "xsl" prefix. All other elements in the file are part of the resulting transformation.

Within the <xsl:stylesheet> element there is at least one <xsl:template> element that matches one or more parts of the XML data document - in the following example, the document root:

<xsl:template match="/">
... transformation rules ...
</xsl:template>
The match attribute uses XPath syntax, an XML expression language that follows many of the rules of directory and file addressing ("/" means the root of the document, "." means the value of the current element, and so on). XPath also supports full querying syntax that lets you find specific parts of an XML document. (I mentioned XPath in the article on reading XML (CFDJ, vol. 4, issue 6), as it's also used by ColdFusion's XMLSearch() function.)

What's XSLT Good For?
Minimally, XSLT can be used to perform XML formatting functions that aren't available in other parts of the CFMX XML API. For instance, in Part 2 of this series I mentioned that an XML document created using the Object method (using the XMLNew() and XMLElemNew() functions) comes out in a single string without any line feeds or indentation. It's well formed and parseable by an XML processor, but hard for the human eye to read.

To fix this, I created a user-defined function (see Listing 1) that merges the XML document with an XSLT stylesheet. This UDF can be used to format and indent any well-formed XML packet, including WDDX. The stylesheet contains a single <xsl:template> that matches the document root:

<xsl:template match="/">
<xsl:copy-of select="."/>
</xsl:template>
The <xsl:copy-of> element copies the entire content of the current object (the document root) to the transformation output. By itself, this <xsl:template> doesn't do much - it just returns the XML document in its original form. The real work is done by the <xsl:output> element that precedes the <xsl:template>:

<xsl:output indent="yes" xalan:indent-amount="2"/>

The "indent" attribute indicates that the XML should be indented. By itself it doesn't actually indent, but it does create line feeds in the appropriate places. To indent I use the "indent-amount" attribute, which isn't part of the XSLT specification, but rather a unique feature of the Xalan processor. Note the use of the "xalan" namespace prefix, which in turn is declared in the stylesheet's root element:

xmlns:xalan="http://xml.apache.org/xslt"

The <xsl:output> element also has an "encoding" attribute that can control the encoding format of the text.

Transforming XML to HTML
XML can be transformed into HTML with an XSLT stylesheet. For this example I'll use the Macromedia Designer/Developer Resource Feed, a list of available DesDev Center articles and columns in a predictable XML format.

To include the formatted contents of the XML file in a Web page, read the XML file with <CFHttp> and the XSLT file with <CFFile>:

<CFHttp url="http://
www. macromedia.com/desdev/
resources/macromedia_
resources.xml"/>
<CFFile action="read" variable="xslt"
file="#ExpandPath('.')#\MMResources.xsl">
Now perform the transformation and output the results:

<CFSet result=XMLTransform (cfhttp.FileContent, xslt)>
<cfoutput>#result#</cfoutput>
This simple code is all you need in your ColdFusion page (see Listing 2). The real work is done by the XSLT stylesheet (see Listing 3). There are two <xsl:template> elements: one for the root element ("macromedia_ resources") and one for the data element ("resource"). The root <xsl:template> creates an HTML table skeleton and uses the <xsl:apply-templates> element to retrieve all resources with a "type" attribute whose value is the word Article:

<table border="1">
<tr><th>Article</th><th>Author</th></tr>
<xsl:apply-templates select="resource[@type='Article']"/>
</table>
The second <xsl:template> matches each "resource" element. It creates an HTML table row and populates its cells with values from the element's children:

<xsl:template match="resource">
<tr>
<td><a href="{url}">
<xsl:value-of select="title"/></a>
</td>
<td><xsl:value-of select="author"/></td>
</tr>
</xsl:template>
The first <td> contains an <a> tag, with its "href" attribute populated from the current resource element's "url" child element. The curly braces indicate use of an XPath expression to retrieve a value from the XML data. The <xsl:value-of> elements also retrieve data with XPath expressions. The result is an HTML representation of the XML data. See the results in Figure 2.

Transforming XML to XML
At some point you may want to transform an XML document into another flavor of XML. This is what XSLT was originally designed for, and it's really good at it!

The XSLT file in Listing 4 is designed to transform the DesDev Resource Feed into a WDDX packet representing an array of structures. The same two XSLT templates are used: one for the root and one for the data element. This time the root <xsl:template> creates the skeleton of a WDDX Array packet:

<wddxPacket version="1.0">
<header />
<data>
<array length="{count(resource[@type=$resourcetype])}">
<xsl:apply-templates select="resource[@type=$resourcetype]"/>
</array>
</data>
</wddxPacket>
The XPath count() function returns the number of items matching the XPath expression. Notice that the type of resource to be retrieved is in a variable named "resourcetype". This variable is set earlier in the file with the <xsl:variable> element.

The second <xsl:template> transforms the current "resource" element into a ColdFusion structure:

<struct>
<var name="TITLE">
<string><xsl:value-of select="title"/></string>
</var>
... other structure items ...
</struct>
This transformation produces a WDDX packet that can be published to a file, saved to a database, or turned into a JavaScript object with the <CFWDDX> tag. The code for running this transformation is in Listing 5.

Limitations
Since the CFMX implementation of XSLT is simply a wrapper for the industry standard Xalan processor, you can do almost anything that's supported by that processor. The XMLTransform() function does, however, have one severe limitation: no parameters.

XSLT processors (including Xalan) allow you to pass in parameters that can then be used in the XSLT code. For instance, in my examples I've filtered on the resource element's "type" attribute. I should be able to pass that variable into the processor instead of having to hard-code its value in the XSLT file. This capability wasn't included in XMLTransform() in the first release of CFMX. Hopefully it will be added in the future. Until then, if you need to pass in parameters, you'll need to revert to the native syntax of the Xalan processor (or other XSLT processor of your choice).

Conclusion
XSLT provides powerful XML processing capabilities in a language that can be learned by any HTML or ColdFusion developer. In the Resources section I've listed some online and published content that I've found to be helpful in learning XSLT.

*  *  *

This concludes the three-part series on CFMX and XML. I've described how to read, create, and transform XML with the new CFMX XML functions. If you've already been working with XML, perhaps these tools will help you reduce coding time and streamline your applications. If you've been avoiding XML due to the complexity of third-party tools, the simplicity of the ColdFusion MX approach may make XML processing more inviting.

XSLT Resources

  • XSLT W3C Recommendation: www.w3.org/TR/xslt
  • Kay, M.H. (2001). XSLT Programmer's Reference, 2nd ed. Wrox.
  • XSLT online documentation: www.zvon.org/xxl/XSLTreference/Output/index.html
  • Apache Xalan documentation: http://xml.apache.org/xalan-j/index.html
  • Comments (0)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.