The other day, Matthew Abbott had contacted me to ask about some advanced JDOM libraries. I have not used JDOM directly in any way so I couldn't really help him. But this got me thinking about XML in general but more specifically, about XML in ColdFusion. I just don't use it that often and certainly, I don't do anything cool with it. So, I thought I would take this opportunity to try some cool stuff.
For this experimentation, I have created two XML document objects: xmlDate and xmlGirls. The xmlDate XML document outlines the agenda for a hot date (who doesn't love pizza and a movie???). The xmlGirls XML document is an XML database of girls:
Launch code in new window » Download code as text file »
CFDumping out the xmlDate XML document, we get:
| | | | ||
| | ![]() | | ||
| | | |
CFDumping out the xmlGirls XML document, we get:
| | | | ||
| | ![]() | | ||
| | | |
Now, our XML document about the date has the girl's ID, but that doesn't really help us out much. What we want to do is copy the properties of the girl from the xmlGirls document to the Girl node of the xmlDate document. My first thought about this was, no problem, just use the AddAll() method for the child nodes collection:
Launch code in new window » Download code as text file »
The problem is that when you run the above code, you get the following ColdFusion error:
WRONG_DOCUMENT_ERR: A node is used in a different document than the one that created it.
The issue, which I had never thought about, was that each Node of an XML document is owned by that document. You can't just use a single XML node in two different places and especially NOT in two different XML documents (just as I can't be both at work and at the movies at the same time!!!).
So, how do we get around this? We have to import the girl node into our xmlDate document before we try and insert it somewhere into our xmlDate XML document object model. To help accomplish this, I have come up with a ColdFusion user defined function, XmlAppend(). This UDF takes two XML nodes from two different XML documents (one from each) and then appends the child nodes of the latter to the child nodes of the former:
Launch code in new window » Download code as text file »
Once we have this nifty ColdFusion XML UDF, we can easily copy the girl properties from the xmlGirls document to the xmlDate document:
Launch code in new window » Download code as text file »
Once the node is copied, our resultant xmlDate XML document looks like this:
| | | | ||
| | ![]() | | ||
| | | |
The girl properties of Girl ID 4 copies over quite nicely. This is some very interesting stuff. It gives me all sorts of ideas about building xml documents in pieces and then easily joining them together to make a bigger, better document (like denormalizing a database).
Download Code Snippet ZIP File
Comments (12) | Post Comment | Ask Ben | Permalink | Other Searches | Print Page
WRONG_DOCUMENT_ERR: A Node Is Used In A Different Document Than The One That Created It
Fantastic Article On Active Release Techniques Using Foam Rollers
Wow! This is a pretty impressive technique.
Do you know where documentation exists that talks about these built-in functions within the XML document object? I've only ever been familiar with the functions in the CF documentation, which aren't nearly this powerful.
Thanks in advance,
Toby
Posted by Toby Reiter on May 14, 2007 at 9:50 AM
@Toby,
Take a look at this:
http://java.sun.com/j2se/1.4.2/docs/api/org/w3c/dom/Node.html
It covers the w3c.org java DOM stuff. It seems that ColdFusion is wrapping around that functionality.
Posted by Ben Nadel on May 14, 2007 at 9:54 AM
Rock on! Thanks for the link!
Posted by Toby Reiter on May 14, 2007 at 10:03 AM
On a recent project, I had the need to copy one node to another 'parent' node. I just used duplicate() on the node and it worked fine.
I was told by a co-worker that it would not work because every XML node has a 'parentNode'. Apparently in CFMX 7, Cf is smart enough to remove that reference when you duplicate(). I am not certain how this would work if I tried to move it to a completely different XML document.
Posted by Scott Stroz on May 14, 2007 at 10:28 AM
Ben,
Check out this XMLMerge UDF I created back in February which uses XSLT to merge.
Regards,
Chris
Posted by Christopher Wigginton on May 14, 2007 at 10:37 AM
@Chris,
That looks pretty cool. I know nothing about XSLT (I have tried to learn it but I just can't seem to get a handle on its seemly irregular programming syntax). I like what you are doing; my only issue with it is that you have to re-parse XML, which might have a lot of over head.
Cool stuff though. I really should learn more about XSLT.
Posted by Ben Nadel on May 14, 2007 at 11:04 AM
Working with XML in Coldfusion is painful and slow. There are much better Java library options available. My blog entry details the problems and a solution using XOM and a StAX processor:
http://orangepips.instantspot.com/blog/index.cfm/2007/3/28/XML-StAX-Processing-with-Coldfusion
Posted by Matthew Lesko on May 14, 2007 at 12:57 PM
@Matt,
That is some interesting stuff. I have not done anything with XML outside of the core ColdFusion installed libraries. I will have to take a look at that other stuff sometime.
Posted by Ben Nadel on May 14, 2007 at 5:46 PM
Just wanted to say thanks for writing this comment! I ran into this same issue while doing some XML work today, and this saved me a TON of headache. Thanks!
Posted by Jonathon Stierman on Oct 1, 2007 at 8:11 PM
Hey ben this is great and it almost solved my problem. Im trying to import a specific child to another xml document in the same parent. I tried to tweak your function to accept a new argument for a specific child but it doesnt seem to be working. Some of these functions are new to me.
Posted by Aaron Wallrich on Feb 4, 2008 at 11:19 PM
Thanks, this worked great for me.
Posted by Larry on Mar 6, 2008 at 2:37 PM
This worked great for manipulating a Word 2003 XML document. I'm using it to insert the contents of one document into another.
Posted by Matthew Fox on Jul 4, 2008 at 5:28 PM