XML parsing in Coldfusion has improved a lot in the last few versions but converting a complex XML object to a Coldfusion structure is still a struggle I beleive. There are a few custom tags out there for doing this but the ones that I have used or know are all only for simple structures, not nested or subnested structures. So I use this little function I and one of my other friends worked on and it works like a charm.
Update (27/12/2008) : The new code has been upload on riaforge and the usage is now very simple . It now takes the XML file and converts to Struct without doing all the Xpath’s before the function call. Here is a sample usage.
[xml]
[/xml]
The new code is here as well – Xml2Struct CFC
Anything below is now outdated :-
Update : Project can now be downloaded from here
A sample usage of the fucntion is below :-
Read the XML file into a Coldfusion variable, this can be a from a file locally or via a CFHTTP call or a webservice call.
[xml]
You need to know the root element of the XML document and pass that to the function.
Then call the function to convert it to a Structure.
[xml]
The function itself can be found here.
The only problem that I notice about this is if the root element has any default namespaces (“xmlns=’blabla’) , the XmlSearch doesnt recognise it. Apart from that, it works like a charm.
The XML file used in this sample can be found here books sample xml file .
Hello Anuj,
Thanks for the awesome .cfc!
I have a quick question. Suppose you have an array inside a struct which only has one element. By default it appears that your function will turn that array into a struct within a struct. Is it possible to force it to make an array within a struct, even though that array has only one element?
Thanks!
@Brad, I will try and re-visit the CFC today/tomorrow. I think there are a few things I can change around and optimize. I will let you know.
Thanks Anuj! I’m not smart enough to figure it out, but I was thinking that somehow how you could program it so that if you use a preset node name, that it would automatically make it an array. For example,
this will be an array
So, if someone uses “arelement” (or something similar), then the function would process that as an array.
This is just a thought.
Thanks again!!
brad
oops, looked liked it deleted the code; bout
-books-
-arelement-This is an array-/arelement-
-/books
(replace – with )
Thanks for the great code!
Works perfect for a quick way to consume an XML webservice then turn around and return a JSON object.
Hi Anuj,
Brad posted this awhile back:
“Hello Anuj,
Thanks for the awesome .cfc!
I have a quick question. Suppose you have an array inside a struct which only has one element. By default it appears that your function will turn that array into a struct within a struct. Is it possible to force it to make an array within a struct, even though that array has only one element?”
I have run into the same need. The inconsistency caused by it creating an array within a stuct followed by a struct within a struct makes it hard to use the output. Any chance you can modify this to always create an array within a struct even though the stuct may only have 1 element?
Hi Dave, That should be easy to change. I will have a look and get back. Give me a couple of days though.
Hi Anuj,
Is it possible to force an array within a struct, even though that array has only one element?
Anuj,
Thanks, I appreciate it. Your code will solve a problem on a project I’m working on. Really appreciate your sharing your work.
Hi Anuj,
I hate to ask because I know that you’re doing me a favor, but is there any chance you might be able to make the modification to the code today? If it doesn’t look like you’ll be able to get to it, I’ll have to figure something else out. My project needs to be done by the morning. Just thought I would ask to see if you might have time.
Thanks!
Dave
Hi Dave, Sorry I have just got back online. I am afraid I wont have any time before the weekend. But it should be a pretty simple change to do and you can give it a shot and try doing it yourself meanwhile. Otherwise I will have a look during the weekend sometime.
Hi Anuj,
I spent the entire day trying to make the change. I put displays in all over the place and still can’t quite follow the logic.
If you’re able to make the change this weekend, I’d greatly appreciate your help.
Hi Anuj,
Hope your weekend is going well. Still look like you might have time to work on this today?
I love how coldfusion is able to work with xml. That makes it a lot easier for programmers to organize the system contents and much easier for editing them. I find that the best use for xml is for detecting an error, or an unwanted ‘member’ inside a long code. I believe this is how OOP should be.
Fred Homes
architects Tucson
Coldfusion can actually do a whole lot more but we need the time and knowledge to explore more. Thanks for sharing Anuj.
I’ve spent ages looking for help with a function for subnested structures; landing here was worth the effort. Job done.
Same! Extremely helpful. Thanks.
Nice code, however, it bombs if the first item in the xml doc is not a node(). For example, if the first item is a comment, XMLSpy is bad about that.
Do you happen to have a function that takes this converted struct and transforms directly back to the original xml?
Have you tried this? http://svn.riaforge.org/soundings/cfcs/toxml.cfc
I will give it a shot, but off the top of your head, will it take ‘node_attributes’ properties and map them as xmlAttributes? This has really been the only stumbling block for me.
Haven’t tried it myself, sorry…
Thank you!!!!!
Great Anuj! Absolutely useful to me this time. So glad I bumped into this blog. Two thumbs up!!! I am in great owe of you. Thanks. More power!
This is throwing away the xmlAttributes if there are xmlChildren, if you need that data I added a line here, ~line 54:
Ah nvm won’t let me post code here =/
I’ll just describe it then,
There are two comments: “recurse call: get complex item:”, line 39 and 53, after the code that runs on the next line, you have access to the XmlAttributes through “axml.XmlChildren[i].XmlAttributes”, just add it however you want to the same struct just referenced
Can’t get the XML attributes to show up…. Useless unless I can access the attributes.
I was having performance issues, since we still use CF for some legacy stuff I’ll post this quick fix, the main issue is ”
” should not be called for every recursion! This is really slow, it only has to be called once ever. So just make a copy of the function and directly assign axml to be arguments.xmlNode – rewrite the recursion call to itself not the original function. Call the original function first, but call your new copied function thereafter, testing gives me about 10x performance increase.
Oops no code, between the double quotes I meant: “axml = XmlSearch(XmlParse(arguments.xmlNode),”/node()”)” and “axml = axml[1]” is the killer, this only ever needs to be called once at the start. Actually dumb of me to say copy the method, just make a small method to call first that does the ‘XmlSearch(XmlParse(arguments.xmlNode),”/node()”)’ and pass the result in. Then you only need one convertXmlToStruct method.
Just gotta give you a HUGE thankyou for this cfc. It makes reading complex SOAP Responses so easy to do!
I get the following error:
Element XMLCHILDREN is undefined in AXML.
I changed this great function a bit to keep the XmlAttributes 😉
<!—
—>
Great function Anuj! I used it with CF9, but after moving to Adobe 2016 it is not working any more! Do you have any idea how I have to change the coding to work with CF2016?
Sorry @KingKassel, haven’t tried it out with CF2016 yet…maybe someone else here on this post can help you out..
Works in CF2018.
Beautiful! It really does work like a charm. Saved me a couple of hours. Many thanks!