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:
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.
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. |