Looping over an array with XML objects - CF8 versus CF9

This post is more than 2 years old.

Here is an interesting little issue I ran into. Given the following simple XML (and I'm typing this on the fly so pardon any typos), imagine you want to loop over the people nodes:

<root> <people /> <people /> <people /> </root>

ColdFusion allows you to treat the people nodes as an array. You can access the second people node by using xmlVar.people[2]. Most folks though will typically want to iterate over each person. Using CFLOOP and it's new array syntax, you might do it like so:

<cfloop index="person" array="#people#"> do stuff </cfloop>

While this works perfectly well in ColdFusion 9, in ColdFusion 8 it fails. The person object is a Java object of the class org.apache.xerces.dom.DeferredElementNSImpl. Now I won't pretend to know how that differs exactly from ColdFusion 9, but the point is, you can't use it in the same way you can with ColdFusion 9.

Of course, the fix for ColdFusion 8 is trivial - change your cfloop to:

<cfloop index="x" from="1" to="#arrayLen(people)#"> <cfset person = people[x]>

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Sean Coyne posted on 1/21/2010 at 12:56 AM

Does isArray(people) return true?

Comment 2 by Raymond Camden posted on 1/21/2010 at 1:01 AM

To be honest, I did not test, but in both cases, the server treated it as an array - the difference was in how it got the element. If that makes sense.

Comment 3 by Marko Simic posted on 1/21/2010 at 2:55 AM

I've done some cf xml work recently, so while I'm in that mood I did some related tests.

<cfxml variable="xml">
<root>
<people>Ray</people>
<people>Bay</people>
<people>Lay</people>
</root>
</cfxml>

<cfoutput>
#isArray(xml.xmlRoot.people)#<br>
#HTMLEditFormat(xml.xmlRoot.people[1])#<br>
#isArray(xml.xmlRoot.xmlChildren)#<br>
#HTMLEditFormat(xml.xmlRoot.xmlChildren[1])#<br>
<cfloop collection="#xml.xmlRoot#" item="person">
- #HTMLEditFormat(xml.xmlRoot[person].xmlText)#<br>
</cfloop>
</cfoutput>

OUTPUT:

NO
<?xml version="1.0" encoding="UTF-8"?> <people>Ray</people>
YES
<?xml version="1.0" encoding="UTF-8"?> <people>Ray</people>
- Ray
- Ray
- Ray

Most interesting is that isArray(xml.xmlRoot.people) is False, while isArray(xml.xmlRoot.xmlChildren) is True.
Anyway I avoid accessing nodes by their names.

I don't have CF8 installed but cosmic forces telling me the result would be the same :)

Comment 4 by Ben Nadel posted on 1/24/2010 at 6:49 AM

Another way to get around this limitation in CF8 is to pass an XmlSearch() result to the array attribute in CFLoop.

Comment 5 by Rodion Bykov posted on 3/18/2010 at 6:39 PM

Saved my day, not first, not last. Thanks again !