Monday 24 Nov 2014   
Add Comment

Parsing XML ColdFusion Tutorial

ColdFusion Tutorial #18

There are many, many uses for XML, and if you use ColdFusion to consume web services, or create data integration processes, then chances are, you will need to work with XML. As of ColdFusion MX there are several tags and functions that make working with XML a snap. In this tutorial I am going to focus on teaching you how to pull the information you need out of XML documents.

demo.cfm

There are several methods you might use to read the XML text into a ColdFusion variable. These methods depend on the source of the XML. If it's in a database you would use CFQUERY, if it is on a file on the ColdFusion server you would read it with CFILE, if you are downloading it from the web you could use CFHTTP or CFFTP, etc. Ultimately, you will end up with a ColdFusion variable that contains the XML text. For this example, and just to keep it simple, I am going to use CFSAVECONTENT to create that variable. This is done on lines 1-20.

As you can see, we are going to work with XML that contains a list of books. The first thing we need to do is use XMLParse() to convert the text contained in the "XMLFile" variable into a ColdFusion XML document object. An XML document object is how ColdFusion represents an XML document, and is much like a ColdFusion structure. This is done on line 23.

In the first example we will simply dump the parsed XML, lines 26-27.

Now you are at the point where you can start pulling the data that you need out of the XML. The best way to pull the information you need out of a ColdFusion XML document object is to use the XMLSearch() function. XMLSearch uses an XPath language expression to search an XML document object and returns a ColdFusion array containing the matching nodes. XPath is a language for addressing parts of an XML document, and the expressions are pretty easy to write once you spend a little time figuring them out.

The basic XPath syntax is similar to file system addressing. If the path starts with a "/", then it represents an absolute path to the element you want.

So if we want to get all the "book" nodes from our XML we could use the example on lines 29-40.

If the path starts with "//" then all elements in the document which fulfill criteria following the "//" are selected. So, if we just wanted to pull a list of authors from our XML, we could use the example on lines 42-50.

With more advanced XPath expressions you can do things like search for nodes with specific values. Here is an example of how to find all the books with titles that contain "ColdFusion". (Keep in mind that these contains() searches are case sensitive.), the example is on lines 52-62.

There are many other ways you can use XMLSearch and XPath to pull the data you need from your XML. To learn more about them visit www.w3.org/TR/xpath/, or just search Google for "XPath Tutorial" and you will find several good ones.



Demo

See this code running!


Download

Download this code as a zip!


Comments

Using your book XML example from above. Say that the returned XML only *sometimes* contained the <author> field of data. When looping and outputting the results, an error would occur. How can this be remedied? A solution w/o a cftry/cfcatch block would be great!
Viper @ Tuesday 04 Dec 2007 - 03:59:24 AM

I believe you can just do an if using structKeyExists
Dale Fraser @ Tuesday 04 Dec 2007 - 10:34:14 AM

Hi,
Great tutorial, helped me get my feet wet with CF and XML. I was wondering if someone may help me though. I am new to CF, and when going through your tutorial i substituted my own XML and get the error:
The prefix "xlink" for attribute "xlink:href" associated with an element type "Order" is not bound.
my xml looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<Response success="true" xmlns:xlink="http://www.w3.org/1999/xlink">
<Orders>
<Order xlink:href="http://localhost/API/80086/Orders/173468288">173468288</Order>
<Order xlink:href="http://localhost/API/80086/Orders/173468285">173468285</Order>
<Order xlink:href="http://localhost/API/80086/Orders/173468225">173468225</Order>
</Orders>
</Response>
Thanks,
Chris.
Chris @ Tuesday 06 May 2008 - 11:27:44 PM

I would do it like this:
<cfsavecontent variable="XMLFile">
<Response success="true" xmlns:xlink="http://www.w3.org/1999/xlink">
<Orders>
<Order xlink:href="http://localhost/API/80086/Orders/173468288">173468288</Order>
<Order xlink:href="http://localhost/API/80086/Orders/173468285">173468285</Order>
<Order xlink:href="http://localhost/API/80086/Orders/173468225">173468225</Order>
</Orders>
</Response>
</cfsavecontent>
<cfset MyXMLDoc = xmlParse(XMLFile)>
<cfset OrderNodes = xmlSearch(MyXMLDoc,"/Response/Orders/Order")>
<cfoutput>
<cfloop from="1" to="#arraylen(OrderNodes)#" index="i">
order = #OrderNodes[i].XmlText#
HREF = #OrderNodes[i].XmlAttributes['xlink:href']#
</cfloop>
</cfoutput>
Scott Bennett @ Wednesday 07 May 2008 - 05:47:16 AM

All the examples I see on the web pass small xml files to xmlParse. Try passing a 20K line UPS xml file to xmlParse. If Coldfusion times out, then increase the timeout in Coldfusion Administrator. Then you may get an 'out of memory error' - then what do you do?
bill @ Sunday 12 Jul 2009 - 10:02:19 AM

Thank you so much for this great example!
jackRoark @ Tuesday 20 Sep 2011 - 08:16:31 AM

Thank you!
john @ Sunday 25 Sep 2011 - 02:33:02 PM

Thank for your tutorial
Anil @ Saturday 07 Jan 2012 - 07:01:58 AM

is there any way to order the cfloop results? currently it is doing it by order the content was added to the feed, with oldest at the bottom - i need oldest at the top...can be done?
hinsel @ Wednesday 15 Feb 2012 - 06:04:20 AM

Click button to add a comment


Author

Scott Bennett


Published

Friday 16 Nov 2007

Original

This tutorial has been modified and published with permission of the author. The original tutorial can be found here
http://www.coldfusionguy.com/ColdFusion/blog/index.cfm/2007/11/15/ColdFusion-Tutorial-Reading-XML-Documents 

Tags

cfdump  cfloop  cfoutput  cfsavecontent  cfset