|
LATEST INTERNET TV STORIES
|
Hot Story XSLT and ColdFusion: Whipping Your XML Data into Shape
XSLT and ColdFusion: Whipping Your XML Data into Shape
By: Matthew Woodward
Aug. 13, 2004 12:00 AM
ColdFusion MX offers a simple and easy way to unleash the power of XSLT for manipulating your XML data. Here's how. From Web services to news and blog data feeds to configuration files, XML is everywhere these days. Far from the buzzword it was when the W3C approved the standard in 1998, XML is now the primary means of data exchange for many organizations and has become the lingua franca of text data in Web application development. Although most of us are aware of how important and ubiquitous XML has become, effective methods for using and manipulating XML data may still be a mystery. The notion of dealing with text data may conjure up nightmarish visions of parsing comma-delimited text files, but, thankfully the days of hunting for line breaks and counting characters are long gone. The hierarchical nature of XML data makes it easy to read for both humans and computers. What XML lacks is the means to manipulate and search itself. Enter XSLT, which provides a powerful way to search (using XPath statements) and to transform XML data from one form into another and - true to form - ColdFusion MX makes using XSLT extremely simple and accessible. In this article I'll describe how XSLT can be used to transform raw XML data into HTML. We'll start with a basic example that uses simple XSLT pattern matching to display XML data as HTML. Then, we'll move on to a slightly more advanced example that includes conditional logic and sorting to make our XML data even more useful. XML: Why Use It? You may also find that even when you don't need to share data, the use of XML may simplify data storage and retrieval. I recently developed an application for a large paint supply company. Each of their product types had widely differing attributes. Based on the data itself, and how it would be used, it made sense to store the product details as XML rather than as separate fields in the database. I kept the high-level attributes (name, catalog number, etc.) as database fields but decided XML was the perfect way to store the more unwieldy product details. Once this XML data was created and stored, however, I needed a way to manipulate and present it to different types of users. XML, Meet XSLT XSLT stands for "Extensible Stylesheet Language Transformations," and, as you may have already surmised, XSLT's job is to transform XML data from one form into another. This might mean taking one XML format and converting it to another (the purpose XSLT was originally designed to fulfill), but XSLT is powerful and flexible enough to transform XML into practically any format you may need. Now you know XSLT's purpose and potential, but you may still be wondering exactly what it is. At its most fundamental level, XSLT is a "flavor"of XML, meaning that XSLT stylesheets are written in XML and must meet all of the requirements of the XML standard. XSLT is also a language, so it has many familiar programming language constructs, such as conditional statements and loops. XSLT's core purpose is to modify XML documents based on patterns (defined using XPath syntax) matched in the XML data. XSLT stylesheets are typically nothing more than a set of rules that tell the XSL processor to match a pattern in an XML document and transform the data within the matching section using the instructions in the XSLT stylesheet. In a sense, XSLT does for XML what regular expressions do for plain text, only much more powerfully and elegantly. Don't be concerned if this seems complicated; the interaction between XML and XSLT will become quite clear through a few simple examples. The beauty of working with XML and XSLT in ColdFusion MX is that all of the complexity of XML and XSL processors is handled by the ColdFusion server. In fact, aside from writing XSLT stylesheets, we need to concern ourselves only with a single ColdFusion function to unleash the power of XSLT. (For the remainder of the article I'm assuming you have some familiarity with XML concepts; if you need a refresher, please see www.macromedia.com/devnet/topics/xml.html or one of the resources listed at the end of this article.) A Simple Transformation Lazy has gotten you into trouble before, so you're going to ignore him this time and use XSLT to transform the XML data into HTML. This is a very common use of XSLT. Most modern browsers support this type of transformation directly within the browser, but because older browsers don't support XSLT and the syntax and available functionality may vary from browser to browser, we're going to use ColdFusion's built-in XSLT processor. Adding Style to Substance If you haven't worked with XSLT before, this may seem a bit foreign, so let's walk through it. At the top of the document is an <xsl:stylesheet> element that contains a couple of attributes. For our purposes you don't need to know anything about this element except that it has to be present in exactly this format in order for some XSLT processors (including the Apache Xalan processor that's built into ColdFusion) to work correctly. Following the first line is an <xsl:output> element that tells the XSL processor what to expect within the document. The W3C's XSLT specification defines xml, html, and text as valid output methods, so in our case we use html. Next, we get to the heart of XSLT: template matching. The <xsl:template match="/animals"> instruction tells the XSLT processor to start at the top of our XML document and find the <animals> element. Conceptually, the use of "/" in XSLT is similar to referencing a Web server's document root by using "/", so this tells the XLST processor to start at the top (the "root" node) of the document. The code following the <xsl:template> tag is a series of output directives that are processed once a match is found, so this is where we place the HTML code that will begin to build our page. Match patterns in XSLT are defined using XPath. According to the W3C, XPath is "a language for addressing parts of an XML document." Another language? Technically, yes, XPath is a separate language. Luckily we don't have to know much about it to use it effectively, so I'm going to keep the dive into XPath relatively shallow for the purposes of this article. Retrieving the Details Note that there are numerous ways to achieve the same result. One method is to use an <xsl:apply-templates> instruction that corresponds to a separate <xsl:template match="something"> instruction within the same stylesheet. Both because I wanted to introduce <xsl:for-each> and also due to some changes we're going to make to our stylesheet in a moment, I opted for the loop here as opposed to another template match. Inside the <xsl:for-each> loop we see the last of our new XSLT instructions, <xsl:value-of>, which tells the XSLT processor to retrieve particular pieces of data from the XML. Data in XML can be stored in two basic ways: as an attribute or as an element. Attributes are name/value pairs that are within an XML tag, whereas elements are separate tag pairs. The value of an element is the text between the element's opening and closing tags. This is admittedly simplified, but for the purposes of this article further distinctions aren't necessary. To retrieve the value of an attribute (a name/value pair that's within an opening tag), simply prefix the name of the attribute with an "@" symbol in the select portion of the <xsl:value-of> instruction. To retrieve the value of an animal's "species" attribute for example, we use the following: <xsl:value-of select="@species" /> Retrieving the value of elements is quite similar. Omit the "@" symbol from the select instruction, use the name of the element as the select value, and XSLT retrieves all of the text between the element's tag pair: <xsl:value-of select="name" /> Before moving on, let's reinforce our budding XSLT knowledge by comparing the <xsl:for-each> loop and XSLT data retrieval to something more familiar to ColdFusion programmers. If we had retrieved this data from a database using cfquery, we would output our table rows like so:
<cfoutput query="animals">
<tr>
<td>#species#</td>
<td>#subspecies#</td>
<td>#name#</td>
<!--- etc. --->
</tr>
</cfoutput>
This is functionally equivalent to our XSLT <for-each> statement:
<xsl:for-each select="animal">
<tr>
<td><xsl:value-of select="@species" /></td>
<td><xsl:value-of select="@subspecies" /></td>
<td><xsl:value-of select="name" /></td>
<!-- etc. -->
</tr>
</xsl:for-each>
Outputting the Results <cffile action="read" file="#ExpandPath('.')# Next, we read the XSLT stylesheet: <cffile action="read" file="#ExpandPath('.')#/animalsHtml.xsl" Finally, we use the XmlTransform() function to transform the XML data and output the results: <cfoutput>#XmlTransform(animalsXml, animalsXsl)#</cfoutput> Voila! You've just magically transformed XML data into HTML, with a little help from ColdFusion (see Figure 2). This example assumes the XML and XSLT documents are retrieved using cffile, but this data can be retrieved other ways, such as from a database or with cfhttp. As long as the first variable passed to XmlTransform() is XML text or a ColdFusion XML variable, and the second variable is XSLT, ColdFusion handles the rest. Felines and Reptiles Don't Mix: Another Transformation Let's imagine that the zookeepers for the felines want a feline-only listing and - as an additional unreasonable demand on you - they want the felines listed in order of feeding time so they can better manage their duties. With traditional text manipulation this would be quite a chore, but with XSLT this task is rather trivial. You don't even have to ask your DBA for a different data feed. Let's extend our recently acquired XSLT pattern-matching skills and instead of outputting all of the animals, we'll output only <animal> elements for which the species attribute is "Feline". Then we'll sort the felines by the <feedingTime> element and we'll have our feline keepers purring. We'll also update the HTML header information so our feline keepers know that this is their list. Listing 4 shows the updated XSLT stylesheet. Most of Listing 4 should look familiar. The first addition is our sort tag, which is simple yet extremely powerful. <xsl:sort select="feedingTime" /> tells the XSLT processor to perform an ascending sort on the elements within the for-each loop, based on the value of the <feedingTime> element. If you've ever dealt with writing your own sorting functionality, you'll appreciate the power of this simple XSLT tag. The other addition is <xsl:if>, which as you might guess is a conditional instruction. <xsl:if test="@species='Feline'"> tells the XSLT processor, "If the species attribute of this animal is Feline, output the following." If the test fails, the XSLT processor skips the output within the <xsl:if> tag for the current loop iteration. XSLT doesn't have a corresponding <xsl:else> instruction, although <xsl:choose>, <xsl:when>, and <xsl:otherwise> can be used to create a switch-like statement, offering additional power for conditional processing. To use ColdFusion to output our newly transformed data, we simply follow the steps outlined above and replace the original XSLT stylesheet with the new one (see Listing 5). Yes, it's really that simple! (See Figure 3.) Conclusion Resources Related Links: LATEST INTERNET TV STORIES
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||