As of ColdFusion MX, there are several tags and functions that make working with XML a snap. In this tutorial I am going to demonstrate how to use these tools to generate an XML document.
The first step is to write a query to get the data we want to export. We are going to export a list of books from the cfbookclub database that comes with ColdFusion.
<!--- Query the Datasource --->
<cfquery name="GetBooks" datasource="cfbookclub">
SELECT B.BookID, B.Title, B.BookDescription, B.Genre, A.FirstName, A.LastName
FROM Books B JOIN Authors A ON B.AuthorID = A.AuthorID
</cfquery>
Now that we have our data, we want to convert it into an XML Document, and as is often the case in programming, there is more than one way to accomplish this task. ColdFusion offers two basic methods for creating XML documents and which one you choose really depends on what you like better.
The first way I will show you is to use the CFXML tag which will process the CFML between its start and end tags, then saves the output as a ColdFusion XML Document Object. This is the method I prefer to use because as you can see from the code below it is much like what we do to generate HTML output for browsers, so I find it easier to work with than the alternative.
<!--- Create an XML Document Object with CFXML --->
<cfoutput>
<cfxml variable="MyXMLDoc">
<?xml version='1.0' encoding='utf-8' ?>
<books>
<cfloop query="GetBooks">
<book id="#GetBooks.BookID#">
<title>#GetBooks.Title#</title>
<description>#GetBooks.BookDescription#</description>
<genre>#GetBooks.Genre#</genre>
<author>#GetBooks.FirstName# #GetBooks.LastName#</author>
</book>
</cfloop>
</books>
</cfxml>
</cfoutput>
<!--- Dump the XML Document Object --->
<h1>Dump from the first method (CFXML)</h1>
<cfdump var="#MyXMLDoc#">
The second way is to use xmlNew() to create a ColdFusion XML Document Object, then use XMLElemNew() to creade the necessary XML nodes. You will see from the example that each node has an XMLChildren property, which contains its child nodes. and works like a ColdFusion array, so you can use array related functions to interact with it. Each node also has an XMLAttributes property that you can interact with like you would a ColdFusion structure. Additionally, each node has a XMLText property which you can use to set the text that goes between that nodes start and end tags.
<!--- Create a ColdFusion XML Document Object --->
<cfset MyXMLDoc = xmlnew()>
<!--- set the XMLRoot to books --->
<cfset MyXMLDoc.XMLRoot = XMLElemNew(MyXMLDoc,"books")>
<cfloop query="GetBooks">
<!--- Add book node for each query row --->
<cfset MyXMLDoc.books.XmlChildren[currentrow] = XmlElemNew(MyXMLDoc,"book")>
<!--- set the id attribute in the book node --->
<cfset MyXMLDoc.books.XmlChildren[currentrow].xmlAttributes.id = "#GetBooks.BookID#">
<!--- create the child nodes for the book --->
<cfset arrayappend(MyXMLDoc.books.XmlChildren[currentrow].xmlChildren, XmlElemNew(MyXMLDoc,"title"))>
<cfset MyXMLDoc.books.XmlChildren[currentrow].title.XMLText="#GetBooks.Title#">
<cfset arrayappend(MyXMLDoc.books.XmlChildren[currentrow].xmlChildren, XmlElemNew(MyXMLDoc,"description"))>
<cfset MyXMLDoc.books.XmlChildren[currentrow].description.XMLText="#GetBooks.BookDescription#">
<cfset arrayappend(MyXMLDoc.books.XmlChildren[currentrow].xmlChildren, XmlElemNew(MyXMLDoc,"genre"))>
<cfset MyXMLDoc.books.XmlChildren[currentrow].genre.XMLText="#GetBooks.Genre#">
<cfset arrayappend(MyXMLDoc.books.XmlChildren[currentrow].xmlChildren, XmlElemNew(MyXMLDoc,"author"))>
<cfset MyXMLDoc.books.XmlChildren[currentrow].author.XMLText="#GetBooks.FirstName# #GetBooks.LastName#">
</cfloop>
<!--- Dump the XML Document Object --->
<h1>Dump from the second method (XMLNew() & XMLElemNew())</h1>
<cfdump var="#MyXMLDoc#">
You can use the toString() function to convert the XML document object to an XML string that can be saved as a file, inserted into a database, submitted to an API, or whatever you need to do with it.
<!--- Use the toString() function to convert the XML Document Object to an XML string --->
<h1>Dump of the toString() function</h1>
<cfdump var="#toString(MyXMLDoc)#">
As you can see from the results of the cfdumps, either of these methods will result in the same output, so you can pick whichever is more comfortable for you.
It's my understanding that there can be no output to the browser prior to the <?xml tag. So I use the cfprocessingdirective tag to suppress whitespace.
I also use the CFContent tag and its type and reset attributes just before outputting the XML.
Lastly you may want to use the caseSensitive attribute of the CFXML tag if the consumer of the XML needs to have the XML element names in a specific case.
See: http://livedocs.adobe.com/coldfusion/7/htmldocs/00...
and http://livedocs.adobe.com/coldfusion/7/htmldocs/00...
and
http://livedocs.adobe.com/coldfusion/7/htmldocs/00...
RSS format? (using Dreamweaver)