Building A ColdFusion XML Document From Scratch

Posted May 14, 2007 at 2:27 PM

Tags: ColdFusion

This is a basic exploration of the ColdFusion XML functions and methodologies that can be used to construct a ColdFusion XML document object model from scratch. I am doing this, not because it is ground breaking, but simply because I have never done it before and it really is something that I should know how to do. Here is my exploratory code - it uses XmlNew() to generate a new XML DOM (document object model) and then other methods and properties to flesh it out:

 Launch code in new window » Download code as text file »

  • <!--- Create a new XML girl object. --->
  • <cfset xmlGirl = XmlNew() />
  •  
  • <!---
  • Create a root xml node under which every
  • other XML node for this document will reside.
  • Notice that we have to create this new root
  • node in the context of our existing XML document
  • so that the document owner is properly set.
  • --->
  • <cfset xmlRoot = XmlElemNew( xmlGirl, "", "girl" ) />
  •  
  • <!---
  • Our new xml node is now owned by the girl
  • document, but it is not yet part of the DOM. We
  • need to explicitly set the root XML node of the
  • girl to point to our newly created XML node.
  • --->
  • <cfset xmlGirl.XmlRoot = xmlRoot />
  •  
  •  
  • <!---
  • Create a node to hold information about her
  • personality (ex. smart, funny, kind). This
  • will be a child of the root node.
  • --->
  • <cfset xmlPersonality = XmlElemNew( xmlGirl, "", "personality" ) />
  •  
  • <!--- Append the personality to the root. --->
  • <cfset ArrayAppend(
  • xmlRoot.XmlChildren,
  • xmlPersonality
  • ) />
  •  
  •  
  • <!---
  • Create a node to hold information about her body
  • (ex. measurements, color, etc). This will be a
  • child of the root node.
  • --->
  • <cfset xmlBody = XmlElemNew( xmlGirl, "", "body" ) />
  •  
  • <!--- Append the body to the root. --->
  • <cfset ArrayAppend(
  • xmlRoot.XmlChildren,
  • xmlBody
  • ) />
  •  
  •  
  • <!---
  • Now, that we have the basic containers down for
  • this XML document, we are going to flesh out the
  • sub structures.
  • --->
  •  
  •  
  • <!---
  • First, we are going to create some properties for
  • the personality. These are going to consist of
  • attribute-driven data values.
  •  
  • NOTE: We cannot just use the reference to xmlPersonality
  • that we generated above. This does not actually point
  • to the XML node that we need to update.
  • --->
  • <cfset xmlRoot.Personality.XmlAttributes.Fun = true />
  • <cfset xmlRoot.Personality.XmlAttributes.Happy = true />
  • <cfset xmlRoot.Personality.XmlAttributes.Nice = true />
  • <cfset xmlRoot.Personality.XmlAttributes.Generous = false />
  • <cfset xmlRoot.Personality.XmlAttributes.Evil = false />
  •  
  •  
  • <!---
  • Next, we are going to create some properties for the
  • body. These are going to consist of attribute-
  • driven data values.
  •  
  • NOTE: We cannot just use the reference to xmlBody
  • that we generated above. This does not actually point
  • to the XML node that we need to update.
  • --->
  • <cfset xmlRoot.Body.XmlAttributes.Hair = "Blonde" />
  • <cfset xmlRoot.Body.XmlAttributes.Eyes = "Brown" />
  • <cfset xmlRoot.Body.XmlAttributes.Bust = 36 />
  • <cfset xmlRoot.Body.XmlAttributes.Waist = 24 />
  • <cfset xmlRoot.Body.XmlAttributes.Hips = 36 />
  •  
  •  
  • <!--- Dump out the resultant XML document object. --->
  • <cfdump
  • var="#xmlGirl#"
  • label="xmlGirl XML DOM"
  • />

When all is said and done, here is a CFDump of the resultant ColdFusion XML document:


 
 
 

 
Creating A ColdFusion XML Document From Scratch  
 
 
 

Then, if we call ToString() on the resultand DOM, we get:

 Launch code in new window » Download code as text file »

  • <?xml version="1.0" encoding="UTF-8"?>
  • <girl xmlns="">
  •  
  • <personality
  • EVIL="false"
  • FUN="true"
  • GENEROUS="false"
  • HAPPY="true"
  • NICE="true"
  • xmlns=""
  • />
  •  
  • <body
  • BUST="36"
  • EYES="Brown"
  • HAIR="Blonde"
  • HIPS="36"
  • WAIST="24"
  • xmlns=""
  • />
  •  
  • </girl>

That was relatively easy to work with. That'll do ColdFusion... that'll do.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page





Reader Comments

May 14, 2007 at 3:56 PM // reply »
19 Comments

Here's an alternate method that I use a lot. I prefer this way because it helps me if I can see the tag structure.
-------------------------------------------------------------------------------

<cfsavecontent variable="xsl">
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:output method="xml" omit-xml-declaration="yes"/>

<xsl:strip-space elements="*"/>

<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>
</cfsavecontent>

<cfxml variable="xmlGirl>
<cfoutput>
<?xml version="1.0" encoding="UTF-8"?>
<girl>
<personality>
<evil>true</evil>
<fun>true</fun>
<generous>false</generous>
<happy>true</happy>
<nice>true</nice>
</personality>
<body>
<eyes>brown</eyes>
<hair>blonde</hair>
<hips>36</hips>
<waist>24</waist>
<bust>36</bust>
</body>
</girl>
</cfoutput>
</cfxml>

<cfcontent variable="#ToBinary(ToBase64(XMLTransform(xmlGirl,xsl)))#" type="text/xml" />


May 14, 2007 at 3:58 PM // reply »
14 Comments

Is there a reason why you are assigning things to a variable, and then putting them into your xml document?

Why do
1) xmlRoot = XmlElemNew( xmlGirl, "", "girl" )
2) xmlGirl.XmlRoot = xmlRoot

When you could just do
1) xmlGirl.XmlRoot = XmlElemNew( xmlGirl, "", "girl" )

??


May 14, 2007 at 4:07 PM // reply »
7,572 Comments

@Matt,

That's cool looking. I really do need to learn more about XSLT. My only issue (other than not know XSLT) was that I was trying to create the XML document without using tags... I agree that tags are WAYYYYY better as you can easily see the structure - but I have done that before. I have never used XmlNew() before this.

@Rich,

I like to break things up into steps because I find it is easier to follow the individual steps. You might lose some sense of the "overall" scope of the problem, but I like to attack the problems individually. For instance, in my example, I am performing 1) Node creation, and 2) Node setting in two steps and explaining them individually... you are doing both of those in a single line of code. It's just a personal preference, but I feel like breaking them apart is slightly better for teaching because it's less you need to understand per code-line.

Sorry if that didn't make any sense.


May 14, 2007 at 5:03 PM // reply »
14 Comments

I can understand that (for teaching purposes). When actually writing something to use this, it seems easier to me to just do it in one line and not have to worry about value/reference issues and remembering to assign things back to your xml object in a second line.

One other note (maybe this is more style based as well)...

Instead of:
xmlRoot.Personality.XmlAttributes.Fun = true
I tend to use:
StructInsert(xmlRoot.PersonalityXmlAttributes, "Fun", true);

This essentially does the same thing, but after spending some time troubling to troubleshoot some weird errors (I have a process that creates a custom xml "file" in memory, then uses that xml transformed with xsl to write CF files), I started doing the second instead of the first to be able to control the case of the xml attributes. Not sure why, but no matter how you type the attribute name in the first example, it always ended up with each letter capitalized (which broke my xsl, which was looking for a specific case of the attribute apparently??). The second example allowed me to control exactly how the attribute name was written out.

Hope that helps somebody else.


May 14, 2007 at 5:12 PM // reply »
7,572 Comments

@Rich,

That is good to know about the case of the tag name when using StructInsert(). I did notice that they were call coming out upper cased in my CFDumps. I figured since CF isn't case sensitive it doesn't matter... but I guess when dealing with XML, more things are case sensitive, including this XSLT that you use.

That is a really good tip to know. Thanks.


May 15, 2007 at 3:02 AM // reply »
7 Comments

Even though I love CF, I have found a really nice Java Library called JDOM to do these things, which, if you put the jar files in your server you can do things in a much nicer (and faster!) way.

check it out!

http://www.jdom.org/


May 15, 2007 at 7:30 AM // reply »
7,572 Comments

@Mark,

That's funny you mention is because my recent XML exploration was triggered by someone asking me about JDOM. I don't know anything about it, but it made me realize that I haven't done too much with XML either. I hear good stuff about this JDOM. Thanks for the link. I will check it out.


Ron
May 16, 2007 at 9:52 AM // reply »
1 Comments

A while ago I had to create an xml document using the described method. That worked very well. The only problem I had was adding a stylesheet to the xml document.
I ended up replacing the first node name, with my stylesheet and adding the first node name again.

Something like:
<cfset xmldoc = replaceNocase(xmldoc, '<rootnode>', '<?xml-stylesheet type="text/css" href="/default.css" ?>
<rootnode>, 'ONE')>

I'm sure there's a better method....... i hope?


May 17, 2007 at 6:53 PM // reply »
7,572 Comments

@Ron,

I am not sure how you get/set the style sheet node with the API. I am trying to look into it, but not coming up with much.


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 21, 2010 at 8:57 PM
The Bourne Ultimatum Starring Matt Damon And Julia Stiles
late to the party, but my observation is this: rewatch carefully for the platonic nature of the relationship between nicki and jason. she never flirts with him. he never comes on to her. they alway ... read »
Mar 21, 2010 at 7:40 PM
Is Simulating User-Input Events With jQuery Ever A Good Idea?
A couple of things. One you embed the initial state of of more-info in the CSS. IMHO, that behavior should be in jQuery: moreInfo.hide(); It shows that the behavior your toggling and closing is mor ... read »
Mar 21, 2010 at 3:59 PM
Exploring ColdFusion Component Runtime Class Properties And Serialization
@Elliott, according to Ben's experiment, serializeJSON() doesn't access the private data by default - it doesn't even access the getHair() method - so trying to clone a Girl.cfc via serializeJSON/des ... read »
Mar 21, 2010 at 3:49 PM
Ask Ben: Javascript String Replace Method
I'm confused a bit by what you are asking, but if had this sentence: The color, red, is in the style statement; style: red;. and wanted to remove all or change all of the commas, colons, and semi-c ... read »
Mar 21, 2010 at 3:13 PM
Ask Ben: Javascript String Replace Method
I am trying to make a java program to count the number of times that these punctuation marks occur in a body of text: , : ; . ! - ' " ? / \ I am using this piece to ferret out the commas: numcommas ... read »
Mar 21, 2010 at 11:13 AM
A New Wrist Pain
@chiropractor suwanee, Spoken like someone trying to sell something. Other than for minor, temporary relief from some back pain, chiropractic treatment is nothing but placebo effect and quackery. ... read »
Mar 21, 2010 at 6:32 AM
ColdFusion CFPOP - My First Look
Apologies... The field name in the db for C. is "BounceCode" It stores the code / message which is returned in the email. Sorry for the confusion. ... read »
Mar 21, 2010 at 6:29 AM
ColdFusion CFPOP - My First Look
@Jose Galdamez, Hi Ben and Jose 1st of all.. big thanks to Jose for his Skype chat a few weeks back. Your time was much appreciated. I have come up with a rather unelegant solution to my problem a ... read »