Duncan's blog

August 18, 2009

Coldfusion and XML – an introduction

Filed under: Coldfusion — duncan @ 9:21 pm
Tags: , , ,

I was doing a bit of investigation into XML in ColdFusion. This is pretty simple stuff, but I didn’t really see any good information about this on the web, so thought it would be worth blogging, as much for my future reference as anyone else’s.

<CFSaveContent> versus <CFXML>

There are various ways of creating XML in ColdFusion. The two simplest ways are cfsavecontent and cfxml.
Method 1 – CFSaveContent:

<cfsavecontent variable="myXML_1">
<country>
	<name>United Kingdom</name>
	<population>61,113,205</population>
	<capital>London</capital>
</country>
</cfsavecontent>

Method 2 – CFXML:

<cfxml variable="myXML_2">
<country>
	<name>United States</name>
	<population>307,212,123</population>
	<capital>Washington, DC</capital>
</country>
</cfxml>

Look almost identical, right? There’s a difference though. CFSaveContent returns a string. CFXML returns a ColdFusion XML object. What’s the difference? Firstly, try outputting both variables.

Variable 1:

<cfoutput>
#HTMLEditFormat(myXML_1)#
</cfoutput>

<country> <name>United Kingdom</name> <population>61,113,205</population> <capital>London</capital> </country>

Variable 2:

<cfoutput>
#HTMLEditFormat(myXML_2)#
</cfoutput>

<?xml version=”1.0″ encoding=”UTF-8″?> <country> <name>United States</name> <population>307,212,123</population> <capital>Washington, DC</capital> </country>

As you can see, the CFXML example has got an XML declaration prepended onto it ( <?xml version=”1.0″ encoding=”UTF-8″?> ). If you were using CFSaveContent you’d usually have to add this in yourself. But that’s not the only difference. This time try dumping out the variables:

<cfdump var="#myXML_1#">

<country> <name>United Kingdom</name> <population>61,113,205</population> <capital>London</capital> </country>

Dumping the first variable is identical to outputting it, because all you have is a string.

<cfdump var="#myXML_2#">

CFDump of CFXML object

Dumping out the variable created with CFXML displays a bit like a structure. [If you click the part that says “xml document” it changes to the ‘long version’. Clicking it again hides the cfdump content.]

So we’ve established the difference, but what advantage does one method have over the other? Because the first variable is just a string, you can put anything you like in there, including invalid XML. However if you try doing that with CFXML, it’ll throw an error (which is a good thing, as you don’t want to accidentally be using something invalid, right?)

XMLParse()

Any time you’re working with XML in ColdFusion, you’ll probably come across the XMLParse function. This takes a block of XML and turns it into an XML object. If you used CFSaveContent, then passed it into XMLParse, you’d get back an object identical to what you’d get if you’d just used CFXML.

You can also pass in an XML object to XMLParse, and it won’t change it. In other words, regardless of if your variable came from CFSaveContent or CFXML, calling XMLParse on it will return the same object.

If you’re getting some XML from anywhere other than CFXML, you probably always want to call XMLParse() on it to turn it into an XML object. If the XML is invalid, it’ll throw an error. You can also pass in a path to a DTD or XML Schema to validate it further.

Functions

When you declare a function in ColdFusion, you can specify an optional returntype attribute. This determines what type of variable is returned from your function (or ‘void‘ if nothing is returned).

When your function is returning XML, you can set returntype=”string” or returntype=”XML” (or returntype=”any”, but that’s a whole other discussion).
If your function is using XMLParse or CFXML to create an XML object, it doesn’t matter if you specify string or XML, it will always return as an XML object.
If you’re using CFSaveContent to create your XML as a string, you can still specify either string or XML, and it will return your XML as a string.
So in other words, regardless of which returntype you use, the variable that’s returned is of a type that matches how it’s created (a string if using CFSaveContent; an XML object if using CFXML).

However if you specify returntype=”XML”, it has to be valid XML, or it will throw an error.

If your function is returning XML to anything other than ColdFusion, e.g. as a webservice, then you want to return it as a string, not an XML object. I’d recommend still using returntype=”XML”, and CFXML to create it (therefore forcing you to create valid XML), but then call ToString() on it when returning.

You probably also want to specify output=”false” (which is good practice most of the time anyway) to avoid getting any extra whitespace appearing at the start of your XML object.

Arguments

Similarly, if you are passing in some XML as a function argument, you can specify type=”string” or type=”XML”. Again, regardless of whether your XML came from CFSaveContent (or elsewhere) as a string, or CFXML / XMLParse() as an XML object, either type=”string” or type=”XML” will be fine. However if you specify type=”XML”, the argument must be valid XML.

If you specify type=”XML”, but it’s an optional argument, I’d recommend doing it like so:

<cfargument name="myXML" type="XML" required="false">

Typically you often see in code default=”” on non-required cfarguments. However it’s not best practice, and if using type=”XML” will thrown an error. If you really need to specify the default attribute, put in a valid bit of XML, e.g.

<cfargument name="myXML" type="XML" required="false" default="<foo>bar</foo>">

Summary

  • Use CFXML instead of CFSaveContent; you won’t have to specify an XML declaration, and it will only work with a valid XML packet
  • CFSaveContent is just a string, so it doesn’t have to be valid XML
  • Use type=”xml” on the argument, even if the value you pass in is a string. It will only accept a valid XML packet
  • If the value could come from anywhere other than CFXML, use XMLParse() to turn what will be a string into a ColdFusion XML object
  • You can use XMLParse() even on a valid XML object (it won’t change it)
  • Even with returntype=”string” if you use CFXML it will return a ColdFusion XML object
  • If you might be returning data to something other than ColdFusion, you would need to turn it into a string first using ToString()
Advertisements

3 Comments »

  1. Thanks Duncan…this was very informative. I appreciate you taking the time to put it together!

    Comment by LarryP — January 26, 2010 @ 10:18 pm | Reply

  2. Hi, post a feedback about the example:

    Variable 2:

    #HTMLEditFormat(myXML_2)#

    should be

    Variable 2:

    #HTMLEditFormat(toString(myXML_2))#

    Cause HTMLEditFormat only accepts string as a parameter while myXML_2 is XML document type.

    Comment by Jawa — October 31, 2010 @ 3:02 pm | Reply

  3. Interesting – you’re correct of course. But at the time I wrote this article, I’m pretty sure I was using HTMLEditFormat on that XML object, without error.

    Comment by duncan — October 31, 2010 @ 7:57 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: