Example: using XML in a ColdFusion application

The example in this section shows how you can use XML to represent data, and how ColdFusion can use XML data in an application. Although the example is too simple to be used in an application without substantial changes, it presents some of the common uses of XML with ColdFusion.

The example receives an order in the form of an XML document, processes it, and generates an XML receipt document. In this case, the order document is in a file, but it could be received as the result of an HTTP request, or retrieved using cfpop, cfftp, or other methods. The ColdFusion page does the following with the order:

  1. Generates a query object from an XML document.
  2. Queries a database table to determine the order discount percentage to use.
  3. Uses a query of queries to calculate the total price, then calculates the discounted price.
  4. Generates the receipt as an XML document.

This example displays the results of the processing steps to show you what has been done.

The XML document

The order.xml document has the following structure:

The following order.xml document works correctly with the information in the CompanyInfo database:

<order id="4323251">
  <customer firstname="Philip" lastname="Cramer" accountNum="21"/>
  <items>
    <item id="43">
      <name>
        Large Hammer
      </name>
      <quantity>
        1
      </quantity>
      <unitprice>
        15.95
      </unitprice>
    </item>          
    <item id="54">
      <name>
        Ladder
      </name>
      <quantity>
        2
      </quantity>
      <unitprice>
        40.95
      </unitprice>
    </item>
    <item id="68">
      <name>
        Paint
      </name>
      <quantity>
        10
      </quantity>
      <unitprice>
        18.95
      </unitprice>
    </item>
  </items>
</order>

The ColdFusion page

The ColdFusion page looks like the following:

<!--- Convert file to XML document object --->
<cffile action="read" file="C:\Neo\wwwroot\examples\order.xml" variable="myxml">
<cfset mydoc = XmlParse(myxml)>

<!--- Extract account number --->
 <cfset accountNum=#mydoc.order.customer.XmlAttributes.accountNum#>
<!--- Display Order Information --->
<cfoutput>
  <b>Name=</b>#mydoc.order.customer.XmlAttributes.firstname# 
       #mydoc.order.customer.XmlAttributes.lastname#
  <br>
  <b>Account=</b>#accountNum#
  <br>
  <cfset numItems = ArrayLen(mydoc.order.items.XmlChildren)>
  <b>Number of items ordered=</b> #numItems#
</cfoutput>
<br><br>

<!--- Process the order into a query object --->
<cfset orderquery = QueryNew("item_Id, name, qty, unitPrice") >
<cfset temp = QueryAddRow(orderquery, #numItems#)>
<cfloop index="i" from = "1" to = #numItems#>
  <cfset temp = QuerySetCell(orderquery, "item_Id",
    #mydoc.order.items.item[i].XmlAttributes.id# ,#i#)>
  <cfset temp = QuerySetCell(orderquery, "name",
    #mydoc.order.items.item[i].name.XmlText#, #i#)>
  <cfset temp = QuerySetCell(orderquery, "qty",
    #mydoc.order.items.item[i].quantity.XmlText# ,#i#)>
  <cfset temp = QuerySetCell(orderquery, "unitPrice",
    #mydoc.order.items.item[i].unitprice.XmlText#, #i#)>
</cfloop>

<!--- Display the order query --->
<cfdump var=#orderquery#>
<br><br>

<!--- Determine the discount --->
<cfquery name="discountQuery" datasource="CompanyInfo">
  SELECT * 
  FROM employee 
  WHERE Emp_Id = #accountNum#
</cfquery>
<cfset drate = 0>
<cfif #discountQuery.RecordCount# is 1>
  <cfset drate = 10>
</cfif>

<!--- Display the discount rate --->
<cfoutput>
  <b>Discount Rate =</b> #drate#%
</cfoutput>
<br><br>

<!--- Compute the total cost and discount price--->
<cfquery name="priceQuery" dbType="query">
  SELECT SUM(qty*unitPrice) 
  AS totalPrice 
  FROM orderquery
</cfquery>
<cfset discountPrice = priceQuery.totalPrice * (1 - drate/100)>

<!--- Display the full price and discounted price --->
<cfoutput>
  <b>Full Price=</b> #priceQuery.totalPrice#<br>
  <b>Discount Price=</b> #discountPrice#
</cfoutput>
<br><br>

<!---Generate an XML Receipt --->
<cfxml variable="receiptxml">
<receipt num = "34">
<cfoutput>
  <price>#discountPrice#</price>
  <cfif drate GT 0 >
    <discountRate>#drate#</discountRate>
  </cfif>
</cfoutput>
  <itemsFilled>  
    <cfoutput query="orderQuery">
    <name>  #name# </name>
    <qty>   #qty#  </qty>
    <price>  #qty*unitPrice#  </price>
    </cfoutput>  
  </itemsFilled>
</receipt>
</cfxml>

<!--- Display the resulting receipt --->
<cfdump var=#receiptxml#>

Reviewing the code

The following table describes the CFML code and its function. For the sake of brevity it does not include code that displays the processing results.
Code
Description
<cffile action="read"
  file="C:\Neo\wwwroot\examples\order.xml"
  variable="myxml">
<cfset mydoc = XmlParse(myxml)>
<cfset accountNum=#mydoc.order.
  customer.XmlAttributes.accountNum#>
Reads the XML from a file and convert it to an XML document object.

Sets the accountNum variable from the customer entry's accountnum attribute.
<cfset orderquery = QueryNew("item_Id, 
  name, qty, unitPrice") >
<cfset temp = QueryAddRow(orderquery,
  #numItems#)>
<cfloop index="i" from = "1" to = #numItems#>
  <cfset temp = QuerySetCell(orderquery,
   "item_Id", #mydoc.order.items.item[i].
   XmlAttributes.id# ,#i#)>
  <cfset temp = QuerySetCell(orderquery,
   "name", #mydoc.order.items.item[i].
   name.XmlText#, #i#)>
  <cfset temp = QuerySetCell(orderquery,
   "qty", #mydoc.order.items.item[i].
   quantity.XmlText# ,#i#)>
  <cfset temp = QuerySetCell(orderquery,
   "unitPrice", #mydoc.order.items.item[i].
   unitprice.XmlText#, #i#)>
</cfloop>
Converts the XML document object into a query object.
Creates a query with columns for the item_id, name, qty, and unitPrice values for each item.
For each XML item entry in the mydoc.order.items entry, fills one row of the query with the item's id attribute and the text in the name, quantity, and unitprice entries that the it contains.
<cfquery name="discountQuery"
    datasource="CompanyInfo">
  SELECT * 
  FROM employee 
  WHERE Emp_Id = #accountNum#
</cfquery>
<cfset drate = 0>
<cfif #discountQuery.RecordCount# is 1>
  <cfset drate = 10>
</cfif>
If the account number is the same as an employee ID in the CompanyInfo database Employee table, the query returns one record. and RecordCount equals 1. In this case, sets a discount rate of 10%. Otherwise, sets a discount rate of 0%.
<cfquery name="priceQuery" dbType="query">
  SELECT SUM(qty*unitPrice) 
  AS totalPrice 
  FROM orderquery
</cfquery>
<cfset discountPrice = priceQuery.totalPrice
  * (1 - drate/100)>
Uses a query of queries with the SUM operator to calculate the total cost before discount of the ordered items, then applies the discount to the price. The result of the query is a single value, the total price.
<cfxml variable="receiptxml">
 <receipt num = "34">
  <cfoutput>
   <price>#discountPrice#</price>
   <cfif drate GT 0 >
    <discountRate>#drate#</discountRate>
    </cfif>
  </cfoutput>
  <itemsFilled>
   <cfoutput query="orderQuery">
    <name>  #name# </name>
    <qty>   #qty#  </qty>
    <price>  #qty*unitPrice#  </price>
   </cfoutput>  
  </itemsFilled>
 </receipt>
</cfxml>
Creates an XML document object as a receipt. The receipt has a root element named receipt, which has the receipt number as an attribute. The receipt element contains a price element with the order cost and an itemsFilled element with one item element for each item.

Comments