Recursion, XML, and Flash Remoting for CFTree Components (Part 1)
In this entry, I explain how to construct a simple XML document for use with a flash CFForm Tree component. It is particularly useful where a field referrences a primary key in the same table. You may need to change it around to suit your needs.
To Start, I setup the CFC.
The first function I write puts all the records into a query, calls the recursive function, formats the XML into an XML document after checking it's validity first, and finally returns the XML document as what it should be, or catches an error and throws it as the primary node.
<cfparam name="result" default="">
<cfparam name="variables.result" default="">
<cfquery name="variables.qryParents" datasource="yourDatasource" debug="no">
SELECT ID, name, ParentID FROM tableName order by ID, ParentID
</cfquery>
<cfset res = makeNodes()>
<cftry>
<cfset tmp = xmlparse(res)>
<cfcatch type="any">
<cfset res='<?xml version="1.0" encoding="UTF-8"?><results id="error" label="error" UID="0" type="error" />'>
</cfcatch>
<cfoutput>
<cfxml variable="result">#res#</cfxml>
</cfoutput>
<cfreturn result>
</cffunction>
The next function is recursive. It builds the XML nodes. This function could also be used for building Unordered Lists instead (if needed), which can be used in DHTML. Being that code recursion doesn't cause huge memory holes in CF, this method is acceptable for use. Being that this snippet is a not really self-explainatory, there are a few comments to help you out.
Rather than wrap everything in a cfsavecontent tag, I have used string concatenation to append to the XML string to avoid all the extra whitespace I know I will get (whitespace does not play nice with the CFXML tag used in the getXMLtree method). Does this add extra overhead to the method? Perhaps if there is a lot of data, but then, this is just an example (and it's a given that the more data there is to process, the longer things will take recursive or not).
This method is very simillar to a method I found here while doing a little digging on recursive functions. Also, the article explains a little bit better why you would need a recursive function - navigation. This was almost perfect for use in a CFTree, but such a component does not care for the UL or LI Elements (and rightly so). Here is the adapted revision for XML :
<cfargument name="parent" type="numeric" required="no" default="0">
<cfset var docXML = "">
<cfif arguments.parent eq 0>
<cfset variables.result = '<?xml version=""1.0"" encoding=""UTF-8""?><results id="root" label="root" UID="0" type="root node">'>
</cfif>
<cfquery name="docXML" dbtype="query">
select * from variables.qryParents where parentID = <cfqueryparam value="#arguments.parent#" cfsqltype="CF_SQL_INTEGER">
</cfquery>
<cfloop query="docXML">
<cfquery name="checkForKids" dbtype="query">
select * from variables.qryParents where parentID = <cfqueryparam value="#docXML.ID#" cfsqltype="CF_SQL_INTEGER">
</cfquery>
<cfif checkForKids.recordcount gt 0>
<!--- this item has children -- add it and then make the recursive call... --->
<cfset variables.result = variables.result & '<result label="#htmleditformat(name)#" id="#htmleditformat(name)#" parent="#arguments.parent#" type="folder" UID="#htmleditformat(ID)#">'>
<cfset makeNodes(parent=docXML.ID)>
<cfelse>
<!--- no children just add it to the xmlstring... --->
<cfset variables.result = variables.result & '<result label="#htmleditformat(name)#" id="#htmleditformat(name)#" parent="#arguments.parent#" type="folder" UID="#htmleditformat(ID)#">'>
</cfif>
<cfset variables.result = variables.result & "</result>">
</cfloop>
<cfif arguments.parent EQ 0>
<cfset variables.result = variables.result & "</results>">
<cfreturn variables.result>
</cfif>
</cffunction>
And finally...
All in all, Nothing too special here. Some repurposed code. In the next entry of this series, I'll show you how I repurposed some ActionScript I found on asfusion to get the flash remoting in play and how I repurposed that to better suit the CFTree component in ColdFusion.

There are no comments for this entry.
[Add Comment]