Title: 
Parsing XML As Query Object In Coldfusion

Word Count:
1009

Summary:
I work in the financial industry as a developer and not that the financial industry has any greater implementation of XML than any other, but web applications that utilize back office processing for loan applications, or new account opening processes, or retail internet banking applications all to some extent make calls to a host. Many times it's a DB2 database, and many times some other process that returns account information or validation information in xml format.

One ...


Keywords:
ColdFusion,Ben Cortese, XML, SQL


Article Body:
I work in the financial industry as a developer and not that the financial industry has any greater implementation of XML than any other, but web applications that utilize back office processing for loan applications, or new account opening processes, or retail internet banking applications all to some extent make calls to a host. Many times it's a DB2 database, and many times some other process that returns account information or validation information in xml format.

One of the fun things that I found working in ColdFusion is the many ways you can manipulate xml data. I'm certain this type of process isn't exclusive to ColdFusion, but I wanted to put it out there anyway. Many developers have a little apprehension about working with new technologies at first, or trying something that hasn't been already tried and true and of course documented heavily. And frankly it's hard to find the extra time with a heavy work load and deadlines to meet to go off experimenting But I managed to put aside some time to look at parsing XML into an object that developers are all familiar with, the Query object. As a developer, writing SQL is common place, so I figured maybe looking at a hybrid approach to XML and SQL in ColdFusion, might prove to offer some benefit.

So I'll show an example of reading in a Phonebook xml document. It will look like this: You can copy this and save it off as phonebook.xml if you like.

<?xml version="1.0"?>
<phonebook>
<contact category="friend">
<firstName>John</firstName>
<lastName>Smith</lastName>
<phone>412-555-1212</phone>
<email>johnsmith@email.comjanesmith@email.combob-jones@mailserver.combill.johnson@someserver.comhttp://turkiyespot.com/jackrobinson.com</a></email>
</contact>
</phonebook>

Reading in the xml is short and sweet simply by using this little block of code.

<cfhttp url="http://turkiyespot.com/http://turkiyespot.com/mywebsite.com/myxmldocs/phonebook.xml</a></a>" method="GET" resolveurl="No" ></cfhttp>
<cfset mydoc = XmlParse(CFHTTP.FileContent)>

Now you've got the xml object in a defined variable name called "mydoc".

Next you set a variable to contain the child element nodes of the xml document and do the same to define the size of the document, which you will see in a bit as to what it's used for.

<cfset pb = http://turkiyespot.com/mydoc.phonebook.XmlChildren</a>>
<cfset size = ArrayLen(pb)>

Now create a query object with the phonebook data. As you can see we already know what the node properties and names are to create the myquery object containing the xml "column names". I say column names to relate the data to a structure like a database.

<cfset myquery = QueryNew("cat, firstName, lastName, phone, email")>

Now that we have the "Columns" of the query object, we use the Size object to give us the parameters to define the Rows like this.

<cfset temp = QueryAddRow(myquery, #size#)>

Now you've established a Query Object 'temp'.

Now comes the part where you fill the Query Object with the data from the XML document. Loop through every "row" in the object adding its value from the xml object like an array.

<cfloop index="i" from = "1" to = #size#>
<cfset temp = QuerySetCell(myquery, "cat",
#mydoc.phonebook.contact[i].XMLAttributes['category']#, #i#)>
<cfset temp = QuerySetCell(myquery, "firstName",
#mydoc.phonebook.contact[i].firstName.XmlText#, #i#)>
<cfset temp = QuerySetCell(myquery, "lastName",
#mydoc.phonebook.contact[i].lastName.XmlText#, #i#)>
<cfset temp = QuerySetCell(myquery, "phone",
#mydoc.phonebook.contact[i].phone.XmlText#, #i#)>
<cfset temp = QuerySetCell(myquery, "email",
#mydoc.phonebook.contact[i].email.XmlText#, #i#)>
</cfloop>

Essentially what you've just done is take the xml and turn it into the same type of data structure you would have when you query a database.

The rest should look familiar to many ColdFusion developers who use ColdFusion Components which is a great practice.

Call the query function using the CFINVOKE. This particular function is if you were to sort the phonebook individuals by last name.

<cfinvoke component="pbook_meths" method="sortLName" returnVariable="Result">
<cfinvokeargument name="q_obj" value="#myquery#">
</cfinvoke>

The output of the result from the function would be no different than that of a normal SQL query.

<table border=1 width=500 align=center>
<th>category</th><th>fist name</th><th>last name</th><th>phone</th><th>email</th>
<cfoutput query="Result">
<tr>
<td>#cat#</td><td>#firstName#</td> <td>#lastName#</td> <td>#phone#</td> <td>#email#</td>
</tr>
</cfoutput>
</table>

The function being called would be stored in its own file as components are in ColdFusion and would look like this.

<cffunction name="sortLName" access="remote" returnType="query">

<cfargument name="q_obj" required="Yes" >

<cftry>

<cfquery name="pbTest" dbType="query">
SELECT *
FROM arguments.q_obj
order by lastName,cat
</cfquery>

<cfcatch type="Any">

<P><cfoutput>#cfcatch.message#</cfoutput></P>

</cfcatch>

</cftry>

<cfreturn pbTest>

</cffunction>

Your component can contain numerous functions manipulating the xml query object just the same as you would a normal query from a database. You don't have the power that a relational database offers of course, but if you're comfortable writing SQL, you may find yourself hitting the ground running with working with xml in ColdFusion.

Thanks and Happy Coding.