Cold Fusion: Way to set default values for XML elements?

I was working on an XML conversion project recently, and found that neither the IsXmlElem(), IsXmlNode(), nor the IsXmlAttribute() functions would work if I was looking for a non-existent element (the throw errors if the element doesn't exist).

I know that XML should all be standardized so all elements always exist. However, this client is using an old Oracle system which doesn't always include all the XML elements. In fact it leaves them out when they're null.

So, I wrote the following function to work like a cfparam for XML elements:

<cffunction name="xmlParam" hint="This function works like a cfparam for xml elements. Returns result." returntype="string" output="No">
   <cfargument name="scope" type="xml">
   <cfargument name="name" type="string">
   <cfargument name="default" type="string">
   <cfset var result = "">
   <cftry>
      <cfset result = Trim(Evaluate("scope.#Arguments.name#"))>
      <cfcatch type="Expression"><cfset result = default></cfcatch>
   </cftry>
   <cfreturn result>
</cffunction>

While, I REALLY hate using a cftry to do this, I can't see any other way. Perhaps you know one??

Comments
Jeff Houser's Gravatar Is there a reason why IsDefined wouldn't work?

<cfif IsDefined("scope.name")>
It's defined
<cfelse>
It is not defined
</cfif>

If you're drilling down into a complicated xml document, with structures embedded in arrays embedded in arrays that include structures and so on then IsDefined won't work (but I suspect that the xmlParam function will run into the same problems with complicated xml documents).
# Posted By Jeff Houser | 8/31/06 11:55 AM
Ken Reiss's Gravatar Thanks for the idea, Jeff! Yes, IsDefined() didn't work either - it, too, threw an error when trying to look for an undefined XML element. Actually, I tried it first, along with StructKeyExists() and XmlSearch() - none of which worked. (forgot to mention in my 1st post on this topic.)

I recall, however, a suggestion you made to me at the last Hartford CFUG meeting, about this topic. You suggested that I loop over the XML, perhaps comparing it with the elements I was requiring and/or putting it into a manual strucutre and then running regular structure tags off it. Being on a limited budget with the client, I didn't try either, but I think they're great idea and probably would be a more solid way of doing this.

I really wonder if Adobe will be adding some sort of a CFPARAM or IsDefined() equivalent for XML documents.
# Posted By Ken Reiss | 8/31/06 10:24 PM
Jeff Houser's Gravatar Ken,

i'm not sure if your specific situation, but in my tests, IsDefined and StructKeyExists appear to be working. Here is some code:

<cfhttp url="http://www.jeffryhouser.com/rss.cfm?mode=full"... timeout="30"></cfhttp>

<cfset xml = xmlparse(cfhttp.filecontent)>

<cfif IsDefined("xml.arg.channel")>
   Element is Defined<Br>
<cfelse>
   Not defined<bR>
</cfif>

<cfif IsDefined("xml.arg")>
   Element is Defined<Br>
<cfelse>
   Not defined<bR>
</cfif>

<cfif IsDefined("xml.rss")>
   Element is Defined<Br>
<cfelse>
   Not defined<bR>
</cfif>

<cfif StructKeyExists(xml,'rss')>
   Element is Defined<Br>
<cfelse>
   Not defined<bR>
</cfif>

<cfif StructKeyExists(xml,'arg')>
   Element is Defined<Br>
<cfelse>
   Not defined<bR>
</cfif>

<cfif StructKeyExists(xml.rss,'channel')>
   Element is Defined<Br>
<cfelse>
   Not defined<bR>
</cfif>

Is this different than your situation?
# Posted By Jeff Houser | 9/1/06 8:03 AM
Jeff P's Gravatar Maybe it might be a CF version thing, but with CF 7, I can use StructKeyExists() and it works pretty well. I am using some very complex xml structures (arrays within nodes with more arrays, etc.).

<cfif StructKeyExists(myXml.RootNode.ChildNode.SomeNodeArray[1]["ChildNodeInArray"], "NameOfNodeIAmLookingFor")>
Hurray!
<cfelse>
Booo
</cfif>
# Posted By Jeff P | 1/5/07 5:33 PM