Chapter 10 - To HTML and Beyond! | |
XSLT For Dummies | |
by Richard Wagner | |
Hungry Minds 2002 |
XML is an excellent general-purpose language for storing structured data. Because XSLT has tremendous flexibility in how it can output XML data, you can create almost any kind of output imaginable. Consider a real-world case in point that I encountered recently. I needed to create JavaScript objects from XML elements, and then use those objects inside a Web page or other JavaScript application. For this section, dont worry if you dont know JavaScript. The point of this example is to illustrate that XSLT can do much more than just output XML and HTML. You can do most anything, and JavaScript is but one example. Also, see Chapter 15 for an example on how to transform XML into a Microsoft Word document. To demonstrate how I solved my JavaScript scenario, Ill use the employees .xml file shown in Listing 10-3. Listing 10-3: employees.xml <?xml version="1.0"?> <employees> <employee id="101"> <lastname>Lamotte</lastname> <firstname>Mitch</firstname> <nickname>The Mitchster</nickname> <title>Director of Sales</title> </employee> <employee id="102"> <lastname>Williams</lastname> <firstname>Tim</firstname> <nickname>Timmy Boy</nickname> <title>Director of Quality Assurance</title> </employee> <employee id="103"> <lastname>Magruder</lastname> <firstname>Randy</firstname> <nickname>Randall</nickname> <title>Senior Engineer</title> </employee> <employee id="104"> <lastname>Drohan</lastname> <firstname>Doug</firstname> <nickname>Tooltime</nickname> <title>Building Director</title> </employee> <employee id="105"> <lastname>Burrer</lastname> <firstname>Phillip</firstname> <nickname>Flip</nickname> <title>Resident Physician</title> </employee> </employees> My goal is transform an employee element like this: <employee id="101"> <lastname>Lamotte</lastname> <firstname>Mitch</firstname> <nickname>The Mitchster</nickname> <title>Director of Sales</title> </employee> Into this JavaScript custom object: // Mitch Lamotte object emp_IDANZJS = new employee("101", "Lamotte", "Mitch", "The Mitchster", "Director of Sales") After I transform the employee elements into JavaScript objects, I can access the employee information from inside my JavaScript code and work with it as native JavaScript, rather than parsing through XML data. The result document I want to create is a text-based file with a .js extension. This type of file (called a JavaScript include file) is used to store JavaScript code and can be accessed from an HTML page using the script element. I use the following stylesheet to perform the transformation: <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <!-- Create constructor function and employees array --> <xsl:template match="/"> // Employee constructor function employee(id, lastname, firstname, nickname, title) { this.id = id; this.lastname = lastname; this.firstname = firstname; this.nickname = nickname; this.title = title; } var employees = new Array(<xsl:value-of select="count(//employee)"/>) <xsl:apply-templates/> </xsl:template> <!-- Create instances of JavaScript objects for each employee --> <xsl:template match="employees"> <xsl:for-each select="employee"> // <xsl:value-of select="firstname"/><xsl:text> </xsl:text> <xsl:value-of select="lastname"/> object var emp_<xsl:value-of select="generate-id()"/> = new employee("<xsl:value-of select="@id"/>", "<xsl:value-of select="lastname"/>", "<xsl:value-of select="firstname"/>", "<xsl:value-of select="nickname"/>", "<xsl:value-of select="title"/>") employees[<xsl:value-of select="position()-1"/>] = emp_<xsl:value-of select="generate-id()"/>; </xsl:for-each> </xsl:template> </xsl:stylesheet> In the first template rule in the preceding code, I declare JavaScript code thats needed to work with the new objects Im creating. (If youre a JavaScripter, I will add that Im defining the employee constructor and an array to store the employee objects that Im creating.) Technical Stuff If my code contained reserved characters , such as < , which appear, for example, in a comparison expression, I would need to wrap that portion of my code in a <![CDATA[ ]]> section or convert the reserved characters to their "escaped" version (for example, < for the < character). In the employees template rule, I use an xsl:for-each instruction to write the JavaScript code needed to create an object instance for that employee. I use the generate-id() function to give each variable a unique name . After creating the object, I add it to an employees array where I could then reference it later. Heres the resulting JavaScript code: // Employee constructor function employee(id, lastname, firstname, nickname, title) { this.id = id; this.lastname = lastname; this.firstname = firstname; this.nickname = nickname; this.title = title; } var employees = new Array(5) // Mitch Lamotte object var emp_IDAGLJS = new employee("101", "Lamotte", "Mitch", "The Mitchster", "Director of Sales") employees[0] = emp_IDAGLJS; // Tim Williams object var emp_IDAMLJS = new employee("102", "Williams", "Tim", "Timmy Boy", "Director of Quality Assurance") employees[1] = emp_IDAMLJS; // Randy Magruder object var emp_IDASLJS = new employee("103", "Magruder", "Randy", "Randall", "Senior Engineer") employees[2] = emp_IDASLJS; // Doug Drohan object var emp_IDAYLJS = new employee("104", "Drohan", "Doug", "Tooltime", "Building Director") employees[3] = emp_IDAYLJS; // Phillip Burrer object var emp_IDA4LJS = new employee("105", "Burrer", "Phillip", "Flip", "Resident Physician") employees[4] = emp_IDA4LJS;
|