XMLSearch in ColdFusion – Unusual Behavior
Well, maybe not completely unusual behavior, but I figured I would document my findings for others anyway.
ColdFusion allows managing of XML documents with relative ease. From the dot notation for traversing an XML document to the various functions to manipulate the document, just about everything is pretty simple when using ColdFusion. Recently, however, I came across an issue with using XMLSearch() It’s probably more of my (previous) understanding of the function call itself rather than it not working correctly, but it still seems a little unusual behavior to me.
I had an XML document that parsed fine.
<cfset INST.parsedData = xmlParse( INST.config ) />
From here I did an XMLSearch for a certain type attribute in my parsed document:
(I grab the first item of the array and set it back to itself so I’m not creating an extra temp variable. The @type is always present in the file so no error will be thrown)
<cfset INST.subObject = xmlSearch( INST.parsedData, "//object[ @type= '" & INST.eachType & "']/") /> <cfset INST.subObject = INST.subObject[ 1 ] />
From here, I wanted to grab a specific item from INST.subObject, but doing the following would always return all of the property nodes with identity=”true” rather than just those specific to the INST.subObject variable
<cfset INST.identityProperty = xmlSearch( INST.subObject, "//property[ @identity= 'true']") />
I guess that the INST.subObject is actually just a pointer of some sort to the original document and when passing the xmlDoc argument into xmlSearch, it then uses the whole original document to perform the actual search.
The solution isn’t too difficult, but may not be completely apparent at first. You just have to create a new xml document of the returned data, thus wiping out any references to the original parsed XML document.
<cfset INST.subObject = xmlparse( tostring( INST.subObject[ 1 ] ) ) /> <cfset INST.identityProperty = xmlSearch( INST.subObject, "//property[ @identity= 'true']") />
INST.identityProperty will now contain the one node within INST.subObject that has an attribute “identity” of true (rather than returning all nodes in the original document with attribute “identity” of true).