Inside Coldfusion MX

You now have enough knowledge about XML to write your own DTDs, XML Schemas, and XML documents, so let's actually use ColdFusion to dynamically create an XML document and parse it.

As we have seen, XML is just a type of text format, so all we will be using is CFQUERY, CFFILE, a new tag called CFXML, and a function called XMLFormat().

Look at the code in Listing 19.5.

Listing 19.5 createpricelistxml.cfm

<cfquery datasource="ICF" name="getCatalog" dbtype="ODBC"> SELECT Product.ProductID, Product.ProductName, Product.ProductPricePerUnit, Product. VendorID, Vendor.VendorID, Vendor.VendorName, Product.ProductSKU, Product. ProductDescription FROM Product, Vendor WHERE Product.VendorID=Vendor.VendorID </cfquery> <cfsavecontent variable="tempxml"><?xml version="1.0" encoding="UTF-8"?> <price-list xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi: noNamespaceSchemaLocation="E:\coldfusion6\workingwithXML\pricelistschema.xsd"> <cfoutput query="getCatalog"> <price-group> <name>#Trim(XMLFormat(getCatalog.ProductName))#</name> <price-element> <product-code>#Trim(XMLFormat(getCatalog.ProductSKU))#</product-code> <description>#Trim(XMLFormat(getCatalog.ProductDescription))#</description> <license type="Server"> <quantity>String</quantity> </license> <list-price>#Trim(XMLFormat(getCatalog.ProductPricePerUnit))#</list-price> </price-element> </price-group> </cfoutput> </price-list> </cfsavecontent> <! - show the XML in the HTML output -> <cfset myXMLDocument=XmlParse(tempxml)> <p>This is a simple XML document that's been generated by the ColdFusion code.</p> <cfdump var=#myXMLDocument#> <cffile action="write" file="#ExpandPath(".")#/pricelist.xml" output="#ToString(tempxml)#">

All this code does is pull information from your database and store it in a temporary variable that it then writes to a file. We could have written it to a file, FTP'd it, sent it via HTTP or email, and so on. The only interesting thing we are doing is making sure that all data from the database is properly formatted for XML by trimming the whitespace and also using XMLFormat, which was introduced in ColdFusion 4.5.

Also note that we are using a function called toString, which makes sure that our XML data is converted to string data before we save it to a file.

Quick Tip

You might notice that we leave no whitespace between the CFSAVECONTENT tag and the opening of the XML tag. The reason for this is that ColdFusion has a tendency to add whitespace to saved content, and this can make our XML unreadable to some XML parsers.

XMLFormat escapes special XML characters so that you can put arbitrary strings safely into XML. The characters escaped by XMLFormat include the following:

  • Greater than sign (>)

  • Less than sign (<)

  • Single quotation mark (')

  • Double quotation mark (")

  • Ampersand (&)

Note

Go to www.w3.org/XML/ to find more information about XML special characters and changes in XML recommendations.

Run the script in your browser and note the output. Now go to the directory and look for the file that the script generated. Drop that file into IE 5.0 or higher or Netscape 6.0. You should see something like Figure 19.2. If you have access to XML Spy or another XML tool, try opening it in that and see what you get.

Figure 19.2. The output from createpurchaseorder.cfm as viewed in IE 6.0.

Before we move on, let's build an XML document again but using a slightly different syntax. We are now going to introduce ColdFusion MX's CFXML tag, which makes working with XML very easy. The CFXML tag has the following basic structure:

<CFXML variable="xmlVarName" caseSensitive="yes" or "no" >

CFXML creates a ColdFusion XML document object that contains the markup in the tag body. This document object is actually a ColdFusion structure that enables you to then work with your XML document as if it were a native ColdFusion variable, which it actually is once you use CFXML to convert it to an XML document object. The CFXML tag enables you to mix XML and CFML tags within its body. ColdFusion processes the CFML code in the tag body and then assigns the resulting text to an XML document object variable.

Let's take Listing 19.5 and change it to look like Listing 19.6.

Listing 19.6 Creatxmlwithcfxml.cfm

<cfquery datasource="ICF" name="getCatalog" dbtype="ODBC"> SELECT Product.ProductID, Product.ProductName, Product.ProductPricePerUnit, Product. VendorID, Vendor.VendorID, Vendor.VendorName, Product.ProductSKU, Product. ProductDescription FROM Product, Vendor WHERE Product.VendorID=Vendor.VendorID </cfquery> <cfxml variable="pricelist"> <pricelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" si: noNamespaceSchemaLocation="E:\coldfusion6\workingwithXML\pricelistschema.xsd"> <cfoutput query="getCatalog"> <price-group> <name>#Trim(XMLFormat(getCatalog.ProductName))#</name> <price-element> <product-code>#Trim(XMLFormat(getCatalog.ProductSKU))#</product-code> <description>#Trim(XMLFormat(getCatalog.ProductDescription))#</description> <license type="Server"> <quantity>String</quantity> </license> <list-price>#Trim(XMLFormat(getCatalog.ProductPricePerUnit))#</list-price> </price-element> </price-group> </cfoutput> </pricelist> </cfXML> <!--- show the XML in the HTML output ---> <p>This is a simple XML document that's been generated by the ColdFusion code.</p> <cfdump var=#pricelist#>

Instead of using the CFSAVECONTENT tag and saving the XML to a file, we have created a ColdFusion object that's an XML document object, which you can see by viewing this page in your browser and seeing the output of CFDUMP (see Figure 19.3).

Figure 19.3. The output of the XML document object structure.

The XML document object structure is a structure that contains a set of nested XML element structures. So why even bother to use CFXML to create XML when it's just as easy to do it the other way? Well, having our XML as a native ColdFusion object will enable us to easily parse, edit, and transform our XML through ColdFusion XML functions (which would be difficult to do otherwise). Table 19.5 introduces you to some of the ColdFusion MX XML functionality.

Table 19.5. Some of ColdFusion MX's XML Functionality

Tag or Function

Description

<cfxml variable="objectName" [caseSensitive="Boolean"]>

Creates a new ColdFusion XML document object consisting of the markup in the tag body. The tag can include XML and CFML tags. ColdFusion processes all CFML in the tag body before converting the resulting text to an XML document object.

If you specify the CaseSensitive="True" attribute, the case of element and attribute names in the document is meaningful. The default is False.

XmlParse("XMLStringVar" [, caseSensitive])

Converts an XML document that is represented as a string variable into an XML document object.

If you specify the optional second argument as True, the case of element and attribute names in the document is meaningful. The default is False.

XmlNew([caseSensitive])

Returns a new, empty XML document object.

If you specify the optional argument as True, the case of element and attribute names in the document is meaningful. The default is False.

XmlElemNew(objectName, "elementName")

Returns a new XML document object element with the specified name.

XmlChildPos(element, "elementName", position)

Returns the position (index) in an XmlChildren array of the Nth child with the specified element name. For example, XmlChildPos(mydoc.employee, "name", 2) returns the position in mydoc.employee.XmlChildren of the mydoc.employee.name[2] element. This index can be used in the ArrayInsertAt and ArrayDeleteAt functions.

IsXmlDoc(objectName)

Returns True if the function argument is an XML document object.

IsXmlElem(elementName)

Returns True if the function argument is an XML document object element.

IsXMLRoot(elementName)

Returns True if the function argument is the root element of an XML document object.

ToString(objectName)

Converts an XML document object to a string representation.

So now you know how to create valid XML dynamically from ColdFusion MX! As you can see, it is very simple, but as with most things, that's the easy part. At some point, we need to be able to get data from the document, view it in another format, or have a program react or respond based on the contents of a document. To do that, we first need to be able to parse XML from ColdFusion.

Категории