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

Recently ran into a problem like that myself. An Ajax function didn't appear to be working. Tracking it back, it made the request properly, and the requested CFC performed properly, but the target DIV wasn't updating. Turned out that the DIV's ID was set by another CFC, and there was about 5 lines of whitespace in the ID attribute. The HTML looked something like this:

<DIV ID="



DivID">

Oddly enough, this was enough to break functionality in IE7, but not in Firefox. Adding output="false" fixed the problem.
# Posted By Matt Osbun | 3/5/07 7:18 AM
Using the CFXML tag in a CFC will preserve the whitepace indentation, so if you follow a standard indentation programming style, you could end up with unwanted whitespace there as well.

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
# Posted By Christopher Wigginton | 3/5/07 9:47 AM
Please excuse the stupid question but if you set the output to false for the cfcomponent will that block output from the individual cffunctions?
# Posted By Michael Brennan-White | 3/5/07 10:49 AM
Nope. output=false in the cfcomponent tag JUST refers to stuff outside cffunction tags.
# Posted By Raymond Camden | 3/5/07 10:52 AM
...and if your CFC extends another CFC, check the parent class(es) too...
# Posted By Ed | 3/5/07 10:55 AM
Thanks for clearing that up. White Space is something I haven't really addressed so far but I know I should
# Posted By Michael Brennan-White | 3/5/07 12:17 PM
When i try to do a test I get a blank page. view source on the blank page shows 41 blank lines. I am not sure if this is causing the page not to work. Below is the sample code and the cfc downloaded from this site, that I am using:
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>&nbsp;</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>
# Posted By xavier | 3/20/07 8:54 PM
I've been fighting the Spry autosuggest for days now. I finally came across your comments and eliminated those nasty not-well-formed errors. But, I still can't get the suggest list to come up. Any chance you could take a look?
# Posted By vaughn lanter | 4/25/07 10:46 PM
Not this week. Been hell. But - the #1 recommendation I can make is Firebug. It will let you ee your AJAX requests and help debug the issue.
# Posted By Raymond Camden | 4/27/07 2:33 PM
Thanks Ray,

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
# Posted By Andrew Mercer | 4/28/07 3:46 PM
Again - try Firebug. See what it seems. Also try turning on debuggin for Spry.

Spry.Data.Region.debug = true;
# Posted By Raymond Camden | 4/28/07 3:55 PM
found the solution here
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
# Posted By Andrew Mercer | 4/28/07 9:51 PM
I had this same problem and it was until I disabled debugging, either in CF Admin or using the enableDisableDebugging(what):

http://www.cflib.org/udf.cfm?id=1142&enable=1

UDF, that I was able to finally get past my remaining XML issue.

~Calvert
# Posted By Calvert Acklin | 12/26/07 10:54 PM