Generating XML from a CFC? Watch out for whitespace
A friend sent in a question this weekend that confounded him to no end. He was generating some XML but kept getting an error in the browser because of extra white space. He had used cfsetting enablecfoutputonly=true. He had used output=false in the method. But he still had a white space issue. And let's face it - ColdFusion likes whitespace more than Paris Hilton likes publicity.
Turns out he had simply forgotten one last hole to plug - the cfcomponent tag. It takes an output=true/false attribute to specify if the initialization area should generate output. If that sounded Greek to you - think of it like this. Any line of code (or white space) outside of cffunction tags is run when the CFC is created. So imagine this CFC:
<cfcomponent displayName="Paris Hilton">
<cffunction name="getTrashier" returnType="void">
<!--- code here --->
</cffunction>
</cfcomponent>
The two blank lines outside of the cffunction tag pair will be part of the output when the CFC is created. To remove it - just add the output tag I mentioned above:
<cfcomponent displayName="Paris Hilton" output="false">
<cffunction name="getTrashier" returnType="void">
<!--- code here --->
</cffunction>
</cfcomponent>
Comments
You also have to turn off output on the following, depending on which type of Application management you use.
Application.cfm
OnRequestEnd.cfm
or
Application.cfc
onRequestStart function
onRequestEnd function
CFM page:
<cfsetting showdebugoutput="no" enablecfoutputonly="true">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitiona...;
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:spry="http://ns.adobe.com/spry">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>sprytest</title>
<script type="text/javascript" src="includes/xpath.js"></script>
<script type="text/javascript" src="includes/SpryData.js"></script>
<script>
var dsTeams = new Spry.Data.XMLDataSet("xml.cfc?method=getTeams", "baseball/teams");
</script>
</head>
<body>
<div spry:region="dsTeams">
<table>
<tr>
<th> </th>
<th><a href="javascript:;" onclick="dsTeams.sort('team')">Team</a></th>
<th><a href="javascript:;" onclick="dsTeams.sort('mascot')">Mascot</a></th>
</tr>
<tr spry:repeat="dsTeams">
<td>{ds_RowID}</td>
<td>{team}</td>
<td>{mascot}</td>
</tr>
</table>
</div>
</body>
</html>
CFC:
<cfcomponent name="Baseball" output="false">
<cffunction name="getTeams" access="remote" returntype="xml" output="false">
<cfset var teams = "" />
<cfset var tmp = "" />
<cfset var xmlObj = "" />
<!---
Create a new query object and populate 5 rows with data. In most cases
your application will be retrieving data from a database via <cfquery> tag.
--->
<cfset teams = queryNew("Team, Mascot", "varchar, varchar") />
<cfset tmp = queryAddRow(teams, 5) />
<cfset tmp = querySetCell(teams, "Team", "Boston", 1) />
<cfset tmp = querySetCell(teams, "Mascot", "Red Sox", 1) />
<cfset tmp = querySetCell(teams, "Team", "New York", 2) />
<cfset tmp = querySetCell(teams, "Mascot", "Yankees", 2) />
<cfset tmp = querySetCell(teams, "Team", "Baltimore", 3) />
<cfset tmp = querySetCell(teams, "Mascot", "Orioles", 3) />
<cfset tmp = querySetCell(teams, "Team", "Toronto", 4) />
<cfset tmp = querySetCell(teams, "Mascot", "Blue Jays", 4) />
<cfset tmp = querySetCell(teams, "Team", "Tampa Bay", 5) />
<cfset tmp = querySetCell(teams, "Mascot", "Devil Rays", 5) />
<!---
Loop through the query and create XML formatted text, which we will then convert to an XML document object.
You could also use Ray Camden's toxml.cfc component to accomplish this.
--->
<cfset xmlObj = "<baseball>" />
<cfoutput query="teams">
<cfset xmlObj = xmlObj & "<teams>" />
<cfset xmlObj = xmlObj & "<team>" />
<cfset xmlObj = xmlObj & "#team#" />
<cfset xmlObj = xmlObj & "</team>" />
<cfset xmlObj = xmlObj & "<mascot>" />
<cfset xmlObj = xmlObj & "#mascot#" />
<cfset xmlObj = xmlObj & "</mascot>" />
<cfset xmlObj = xmlObj & "</teams>" />
</cfoutput>
<cfset xmlObj = xmlObj & "</baseball>" />
<!---
Convert the XML formatted text to an XML document object.
--->
<cfset xmlObj = xmlParse(xmlObj) />
<!---
Spry will not recognize the returned XML without this line. Thanks to Bruce Phillips (www.brucephillips.name) for this tip.
--->
<cfcontent type="application/xml; charset=UTF-8">
<cfreturn xmlObj />
</cffunction>
</cfcomponent>
been pulling my hair out over this one - didn't know about output attribute for the component.
But my spry page is still not working :-(
If I save the output in my broswer from the cfc call into an xml file and point spry at that it works.
I am running it through apache proxy url as the cfc is on a differnent domain. I will try a local cfc and see what happends.
Any other suggestions anyone?
TIA
Spry.Data.Region.debug = true;
http://www.brucephillips.name/blog/index.cfm/2006/...
Spry needs this
<cfcontent type="application/xml; charset=UTF-8">
I put it the line before cfreturn
http://www.cflib.org/udf.cfm?id=1142&enable=1
UDF, that I was able to finally get past my remaining XML issue.
~Calvert


<DIV ID="
DivID">
Oddly enough, this was enough to break functionality in IE7, but not in Firefox. Adding output="false" fixed the problem.