Accessibility
Icon or Spacer
   

Transforming XML to Application Data Using WDDX

by Anne Sandstrom, Allaire Documentation Group

Editor's Note: This article uses CSS properties that may not be rendered by all browsers. For best results, you should view this one in IE 4.0+. You can also download a ZIP archive of this page which contains the article in HTM and PDF format.

Abstract

This tech note introduces XML, and provides an example of transforming XML data to application data using WDDX.

Contents

What is XML?

XML is a tag-based, user-defined language. Unlike HTML, whose purpose is to format data, XML is used to identify data.

For example, suppose you maintain a Web site that contains information about books. Using HTML, you might enclose the title of each book in the <H1></H1> tag. However, if you wanted to create and then update a table of contents that included all the book titles on your site, you'd have to do a lot of cutting and pasting because HTML doesn't offer a way to programmatically handle entities enclosed in tags other than to display them on the current page.

Enter XML.

Instead of simply displaying your book titles using the same format, XML allows you to identify an entity as a book title. You can then programmatically manipulate all the book titles on your site. And, if another site uses the same book title definition in XML that you do, you can work with them in the same way.

This has far-reaching implications for exchanging and sharing industry-wide standard data, such as banking information.

What Does XML Look Like?

Like HTML, XML is a tag-based language. Unlike HTML, XML consists of user-defined tags to describe elements of data. For example, a book might contain the elements "title," "author," "pagecount," "copyright," and "publisher."

In the example below, we'll look at an invoice as it might appear in XML. The invoice contains information about the contractor who submitted it. It also contains information about the particular tasks, hours, and amounts. The information can be represented as follows:

INVOICE

Invoice ID: 12345

Date submitted: 10/24/1999

Employee ID: 1048

Name: Marie Smith

Address: 124 Brown Street, Warren, VT USA 12345

Phone:

802-555-1111

Fax:

802-555-2222

Email:

msmith@myownisp.com

Date

Hours

Description

Currency

Amount

9/21/99

8

Create graphics

USD

45.00

9/22/99

7.5

Edit graphics

USD

45.00

9/23/99

4

Edit graphics

USD

45.00

9/23/99

4

Resize graphics

USD

45.00

9/24/99

8

Update graphics

USD

45.00

Here is an example of the invoice as it might appear in XML:

<?xml version="1.0" ?>

<!--invoice from AP Corporation -->

<invoice>

    <invoiceID>12345</invoiceID>

    <dateSubmitted>1999-10-24T04:10:56-05:00</dateSubmitted>
    
    <contractorInfo>
        <employeeID>1048</employeeID>
        <firstName>Marie</firstName>
        <lastName>Smith</lastName>
        <address>
            <street>124 Brown Street</street>
            <city>Warren</city>
            <state>VT</state>
            <zip>12345</zip>
            <country>USA</country>
        </address>
        <voice>802-555-1111</voice>
        <fax>802-555-2222</fax>
        <email>msmith@myownisp.com</email>
    </contractorInfo>

    <billableHours>

        <item>
            <date>1999-09-21</date>
            <hours>8</hours>
            <description>Create graphics</description>
            <rate>
                <currency>USD</currency>
                <amount>45.00</amount>
            </rate>
        </item>
        
        <item>
            <date>1999-09-22</date>
            <hours>7.5</hours>
            <description>Edit graphics</description>
            <rate>
                <currency>USD</currency>
                <amount>45.00</amount>
            </rate>
        </item>
        
        <item>
            <date>1999-09-23</date>
            <hours>4</hours>
            <description>Edit graphics</description>
            <rate>
                <currency>USD</currency>
                <amount>45.00</amount>
            </rate>
        </item>
        
        <item>
            <date>1999-09-23</date>
            <hours>4</hours>
            <description>Resize and compress graphics</description>
            <rate>
                <currency>USD</currency>
                <amount>45.00</amount>
            </rate>
        </item>
        
        <item>
            <date>1999-09-24</date>
            <hours>8</hours>
            <description>Update graphics</description>
            <rate>
                <currency>USD</currency>
                <amount>45.00</amount>
            </rate>
        </item>

    </billableHours>
    
</invoice>

Notice that the invoice contains elements such as "billingAddress," which, in turn, contains elements such as, "firstname," "lastname," and "street."

Using XML with ColdFusion

Now, suppose your finance department uses a ColdFusion application to update the database that keeps track of your contracting expenses. The database you want to maintain contains the following fields:

  • EmployeeID
  • Description
  • Hours
  • Amount
  • Currency

All of your contractors submit their invoices in XML, as in the example above. You need to take the data from the XML invoices and use it to update the contracting expenses database.

Ways to Handle XML in a ColdFusion Application

There are two distinct paths to go from XML to application data: one uses WDDX, while the other relies on the DOM Tree. The following diagram illustrates both methods:

The remainder of this tech note will describe the method that uses WDDX.

Transforming XML Data Using WDDX

Web Dynamic Data Exchange (WDDX) is a format that allows for exchanging and sharing complex data. It is, in fact, XML-based Since ColdFusion applications completely support WDDX, it is a natural choice for dealing with XML data.

Transforming XML data to application data via WDDX is a two step process:

  • Transform XML to WDDX using a style sheet (Extensible Stylesheet Language) with XSL Transformations (XSLT).
  • Use the CFWDDX tag to handle the transformed data.

Transforming XML to WDDX with XSLT

In order to manipulate the XML data into a more easily usable form, you use eXtensible Stylesheet Language (XSL). More than simply formatting the XML data, XSL produces a result tree, which you can further modify.

Creating an XSL stylesheet

First, you need to create an XSL stylesheet, as follows.

<!--

    File:                 invoice2wddx.xsl
    Author:             Simeon Simeonov
    Version:            0.2
    Last modified:        December 17, 1999
    
    This stylesheet provides a default translation between the
    invoice format and a WDDX packet describing its structure.
    
    In addition, it can be used as a template for mapping other
    types of XML into WDDX.  
    
-->


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/
Transform">
    
<!-- Match invoice root & emit WDDX packet wrapper -->
<xsl:template match="/invoice">
    <wddxPacket version="1.0">
        <header/>
        <data>
            <struct>
                <xsl:apply-templates/>
            </struct>
        </data>
    </wddxPacket>
</xsl:template>


<!-- Process all elements that map to array variables -->
<xsl:template match="billableHours">

    <var name="{name(.)}">
        <array length="{count(*)}">
            <xsl:apply-templates/>
        </array>
    </var>
    
</xsl:template>


<!-- Process all elements that map to struct variables -->
<xsl:template match="invoice|contractorInfo|address|item">

    <var name="{name(.)}">
        <struct>
            <xsl:apply-templates/>
        </struct>
    </var>
    
</xsl:template>


<!-- Process all elements that map to string variables -->
<xsl:template 
match="firstName|lastName|street|city|state|zip|country|voice|fax|email|
description|currency">

    <var name="{name(.)}">
        <string>
            <xsl:value-of select="text()"/>
        </string>
    </var>
    
</xsl:template>


<!-- Process all elements that map to number variables -->
<xsl:template match="invoiceID|employeeID|hours|amount">

    <var name="{name(.)}">
        <number>
            <xsl:value-of select="text()"/>
        </number>
    </var>
    
</xsl:template>


<!-- Process all elements that map to date-time variables -->
<xsl:template match="dateSubmitted|date">

    <var name="{name(.)}">
        <dateTime>
            <xsl:value-of select="text()"/>
        </dateTime>
    </var>
    
</xsl:template>


</xsl:stylesheet>

Downloading an XML processor

Once you have created your stylesheet, you can then use it in processing the XML. You need to determine which XSL processor you want to use. This example uses the XML parser LotusXSL v0.19.1, available at http://www.alphaworks.ibm.com/.

When you download the .jar file, make sure to put it on the class path set in ColdFusion Administrator.

Tip Before you can run the XML parser, make sure you have installed the JDK 1.2 or JRE 1.2, which can be found at http://java.sun.com/products/jdk/ 1.2/jre/index.html.

Processing the XML

Once you have installed the XML parser, you can use the CFOBJECT tag to process the XML.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
    <title>Process XML</title>
</head>

<body>


<!--- Create a Node class to get at its attributes --->    
<CFOBJECT TYPE=JAVA 
        ACTION=CREATE 
        CLASS="java.io.FileWriter" 
        NAME=Writer>
<cfset Writer.init("c:\Inetpub\wwwroot\xml_technote\wddx_test.out")>

<CFOBJECT TYPE=JAVA 
        ACTION=CREATE 
        CLASS="java.io.PrintWriter" 
        NAME=PrintWriter>
<cfset printWriter.init(Writer)>

<!--- Create the parser factory, and get the parser --->
<CFOBJECT 
    TYPE=JAVA 
    ACTION=CREATE 
    CLASS="com.lotus.xsl.XSLProcessor"
      NAME=xslProcessor>    
    
<cftry>    
<CFSET xslProcessor.process
    ("c:\Inetpub\wwwroot\xml_technote\invoice.xml", 
     "c:\Inetpub\wwwroot\xml_technote\invoice2wddx.xsl", PrintWriter)>
<cfcatch type="ANY">
    <br>
    <cfoutput> Exception : #CFCATCH.Detail# </cfoutput>
</cfcatch>
</cftry>


</body>
</html>

Resulting WDDX packet

Once you process the XML using the stylesheet, the result is a WDDX packet, which is a flattened representation of the data. Because the WDDX packet represents the hierarchy in a flattened form, it makes it possible to share the data across the Web and across applications without losing important information about the data's hierarchy.

The WDDX packet that results from processing the XML with the parser looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<wddxPacket version="1.0"><header/><data><struct>

    <var name="invoiceID"><number>12345</number></var>

    <var name="dateSubmitted"><dateTime>1999-10-24T04:10:56-05:00</
dateTime></var>
    
    <var name="contractorInfo"><struct>
        <var name="employeeID"><number>1048</number></var>
        <var name="firstName"><string>Marie</string></var>
        <var name="lastName"><string>Smith</string></var>
        <var name="address"><struct>
            <var name="street"><string>124 Brown Street</string></var>
            <var name="city"><string>Warren</string></var>
            <var name="state"><string>VT</string></var>
            <var name="zip"><string>12345</string></var>
            <var name="country"><string>USA</string></var>
        </struct></var>
        <var name="voice"><string>802-555-1111</string></var>
        <var name="fax"><string>802-555-2222</string></var>
        <var name="email"><string>msmith@myownisp.com</string></var>
    </struct></var>

    <var name="billableHours"><array length="5">

        <var name="item"><struct>
            <var name="date"><dateTime>1999-09-21</dateTime></var>
            <var name="hours"><number>8</number></var>
            <var name="description"><string>Create graphics</string></
var>
            
                <var name="currency"><string>USD</string></var>
                <var name="amount"><number>45.00</number></var>
            
        </struct></var>
        
        <var name="item"><struct>
            <var name="date"><dateTime>1999-09-22</dateTime></var>
            <var name="hours"><number>7.5</number></var>
            <var name="description"><string>Edit graphics</string></var>
            
                <var name="currency"><string>USD</string></var>
                <var name="amount"><number>45.00</number></var>
            
        </struct></var>
        
        <var name="item"><struct>
            <var name="date"><dateTime>1999-09-23</dateTime></var>
            <var name="hours"><number>4</number></var>
            <var name="description"><string>Edit graphics</string></var>
            
                <var name="currency"><string>USD</string></var>
                <var name="amount"><number>45.00</number></var>
            
        </struct></var>
        
        <var name="item"><struct>
            <var name="date"><dateTime>1999-09-23</dateTime></var>
            <var name="hours"><number>4</number></var>
            <var name="description"><string>Resize and compress 
graphics</string></var>
            
                <var name="currency"><string>USD</string></var>
                <var name="amount"><number>45.00</number></var>
            
        </struct></var>
        
        <var name="item"><struct>
            <var name="date"><dateTime>1999-09-24</dateTime></var>
            <var name="hours"><number>8</number></var>
            <var name="description"><string>Update graphics</string></
var>
            
                <var name="currency"><string>USD</string></var>
                <var name="amount"><number>45.00</number></var>
            
        </struct></var>

    </array></var>
    
</struct></data></wddxPacket>

Using CFWDDX to Manipulate the WDDX Packet

Once you have the WDDX packet, as above, you can simply manipulate it as you can any WDDX packet using the CFWDDX tag. For more information on using CFWDDX, see Developing Web Applications and the CFML Language Reference.