Paraming ColdFusion XML Documents With CFParam

Posted May 4, 2009 at 9:00 AM by Ben Nadel

Tags: ColdFusion

The other day, I was updating some old code that interacted with an XML web service. The code in question was expecting a certain XML structure to be returned, but the API had changed (or had never worked properly - I didn't write the original), and started erroring out. The problem was that XML response did not contain all the nodes that were expected in the calling code. As I was not familiar with the API, I figured the fastest way to karate chop the situation was simply to param the XML nodes if they did not exist.

But, how to do that easily? For fun, not really expecting it to work, I tried using the CFParam tag. And, much to my surprise, it totally worked! As with any CFParam tag, there is going to be the overhead of creating values that might not be used; but, in a pinch, this was the perfect solution.

To demonstrate this concept, I put this demo together:

  • <!--- Create an XML document. --->
  • <cfxml variable="xmlGirl">
  •  
  • <girl>
  • <name>Libby</name>
  • <height>5'7"</height>
  • </girl>
  •  
  • </cfxml>
  •  
  •  
  • <!---
  • Param nodes in the XML document that we expect to exist.
  • We can do this to make sure an XML response is always
  • presented in uniformity.
  • --->
  • <cfparam
  • name="xmlGirl.girl.hair"
  • type="xml"
  • default="#XmlElemNew( xmlGirl, 'hair' )#"
  • />
  •  
  •  
  • <!--- Output new XML document structure. --->
  • <cfdump
  • var="#xmlGirl#"
  • label="XML After CFParam"
  • />

Notice that the original XML document does not have a "Hair" node. The Hair nodes gets paramed using CFParam and the XmlElemNew() function. And, running the above code, we get the following CFDump output:

 
 
 
 
 
 
ColdFusion XML Document Has New Nodes After CFParam Tag Param'd Xml Node. 
 
 
 

As you can see, the Hair node was successfully paramed in the target ColdFusion XML document. Cool stuff! I think with a little more elbow grease, it would be easy to make a function that params an entire XML document to create a unified API response. There would be a significant overhead of course; but, the overhead might be worth not having to deal with a bunch of conditional checks within the XML processing. Another blog post perhaps?

NOTE: The CFParam tag will work with both dot-notation and array-notation (ex. xmlGirl.girl[ 'hair' ]) when working with XML documents.




Reader Comments

May 4, 2009 at 9:20 AM // reply »
48 Comments

Ben - does this handle multiple nodes? In other words - if you had n girl nodes would it add a <hair> child to each node? I don't mess with XML as much as I should so sorry if that's a dumb question ;)


May 4, 2009 at 9:28 AM // reply »
66 Comments

This is kind of interesting. I'm not sure I would have tried that myself considering I usually keep my CFParam's at the top of my pages.

I know you've done a boatload of posts on xml and thought you already had a different way of dealing with missing nodes though.


May 4, 2009 at 10:01 AM // reply »
11,243 Comments

@Todd,

I believe it would only param the first child. I believe that when you use the pseudo node sets (using named dot notation instead of the XmlChildren collection), it treats the dot as the first node in that given set; as such, I think even if there were multiple Girl nodes, it would only work on the first one.

If you needed to param multiple nodes, I bet you can use the array notation:

<cfparam name="xmlGirl.girl[ 1 ].hair" ... />

CFParam should work that way, assuming that it is compatible with the way XML nodes are inserted into the document.

... Hmm, you just gave me an idea! Thanks :)

@Steve,

I haven't had to deal with non-standard API responses much. Also, I would normally put CFIF statements in my processing. But, since I was not familiar with the API (I was updating someone else's old code), I thought figured this would be safer that CFIF statements.


May 4, 2009 at 10:02 AM // reply »
45 Comments

@todd: Nope it only does the first node, you would have to loop over each <girl> node I guess.


May 4, 2009 at 10:07 AM // reply »
45 Comments

Ben beat me to it! I tested it as well, and you can just use the array notation. The XML document would need a <girls> root node though of course :)


May 4, 2009 at 10:28 AM // reply »
11,243 Comments

@Justin,

Great minds think alike :D

@Todd,

Your question gave me an idea: because XML nodes are inserted by copy, not by reference, we can minimize the CFParam overhead by factoring out new node creation if we need to param nodes over a collection of elements:

http://www.bennadel.com/index.cfm?dax=blog:1579.view

Thanks!


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 23, 2013 at 3:55 AM
Javascript Array Methods: Unshift(), Shift(), Push(), And Pop()
very interesting and helpful too. ... read »
May 22, 2013 at 5:35 PM
Script Tags, jQuery, And Html(), Text() And Contents()
This is still an issue 2 years later. jQuery is supposed to remediate these cross browser issues, no? I have been unable to find any statement from the jQuery team calling this behavior "by de ... read »
May 22, 2013 at 12:44 PM
Ask Ben: Query Loop Inside CFScript Tags
In cf10, if you call a function that has: local.result = {}; local.result.msg = ""; local.svc = new query(); local.svc.setSQL("SELECT * FROM..."); local.obj = local.svc.exe ... read »
May 22, 2013 at 12:29 PM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben: What version of Java are you using? Also, did you test users.id to see what Java reports as the data type? I wonder if it's not a Java primitive data type, but getting returned as something ... read »
May 22, 2013 at 11:47 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Dana, Awesome - so it looks like this bug was fixed in ColdFusion 10. Thanks so much for double-checking that. ... read »
May 22, 2013 at 11:37 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
When I c&p and run on cf10, I get: Selected User IDs: 1,4 User 1 selected: YES - YES User 2 selected: NO - NO User 3 selected: NO - NO User 4 selected: YES - YES User 5 selected: NO - ... read »
May 22, 2013 at 11:27 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Tom, Good thought, but no dice. Both of these still exhibit the same behavior: users.id[ users.currentRow ] users[ "id" ][ users.currentRow ] It's just something whacky happening with ... read »
May 22, 2013 at 11:07 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
Could your problem be that "users.id" is actually an ARRAY, not a single value? Perhaps try it again with "users.id[1]" (I only have CF8 here at work). ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools