Creating XML Objects
Listing 14.3 shows an XML document that represents three employees in a corporation.
Listing 14.3. SingleCompany.xmlA Basic XML Document
In order to use this document effectively from ColdFusion, we must turn this XML document into an XML object , much like a set of nested structures and arrays. One way to do that is by using the <cfxml> tag.CAUTION
<company>
<employee ssn="123-45-6789">
<first>Ed</first>
<last>Johnson</last>
<department>Human Resources</department>
</employee>
<employee ssn="541-29-8376">
<first>Maria</first>
<last>Smith</last>
<department>Accounting</department>
</employee>
<employee ssn="568-73-1924">
<first>Eric</first>
<last>Masters</last>
<department>Accounting</department>
</employee>
</company>
The two terms XML document and XML object are not interchangeable, although some people use them as such. In this book, XML document refers to a string of XML-encoded text, and XML object refers to a complex variable that ColdFusion can manipulate directly.
Using <cfxml>
Listing 14.4 creates an XML object out of an XML document by using <cfxml>, and displays it by using <cfdump>.
Listing 14.4. cfxml.cfmUsing <cfxml> to Create an XML Object
<cfxml> returns the same kind of XML object that is returned by XmlParse(), the only difference being that XmlParse() creates an XML object based on an XML document stored in a string variable. You will likely use XmlParse() more often than you use either <cfxml> or XmlNew(), which is described later in the chapter..TIPYou may have noticed the caseSensitive attribute in the <cfxml> call earlier. By default, ColdFusion is not case-sensitive in its XML handling. However, because other platforms may be case-sensitive, you should make sure your XML documents are case-sensitive as well.
<cfxml variable="xmlObject" caseSensitive="Yes">
<company>
<employee ssn="123-45-6789">
<first-name>Ed</first-name>
<last-name>Johnson</last-name>
<department>Human Resources</department>
</employee>
<employee ssn="541-29-8376">
<first-name>Maria</first-name>
<last-name>Smith</last-name>
<department>Accounting</department>
</employee>
<employee ssn="568-73-1924">
<first-name>Eric</first-name>
<last-name>Masters</last-name>
<department>Accounting</department>
</employee>
</company>
</cfxml>
<cfdump var="#xmlObject #">
Accessing XML Elements and Attributes
So now that we have an XML object in memory, how do we access its elements and their properties? ColdFusion makes it easy for us by exposing the elements and attributes as if they were arrays and structures. For example, to access the second employee element, I'd use syntax like this:
Notice the bracket notation, just as if I were accessing a set of nested structures with an array at the end. What if I wanted to access the second employee's first name? I'd extend the syntax like this:
xmlObject["company"]["employee"][2]
Notice the xmlText property at the end of the reference. If I had just referred to the first-name element, that expression would have returned an XML element object reference rather than a string. The xmlText contains the text stored in the element object itself.What about attributes? Let's say I wanted to access the SSN of the third employee. I'd use similar syntax, like this:
xmlObject["company"]["employee"][2]["first-name"].xmlText
Because attributes are always strings, attributes do not require that you put xmlText at the end of the reference.TIPWhen referencing element and attribute names, I always use bracket notation (["company"]) rather than dot notation (.company). I do this for two reasons. First, XML is case-sensitive, and dot notation often has problems with mixed-case documents. Second, you cannot use dot notation with element names that contain hyphens, so for consistency's sake, I use bracket notation everywhere.The form of XML notation we've been using so far, in which the element names are used like the names of arrays, is known as short form notation :
xmlObject["company"]["employee"][3].xmlAttributes["ssn"]
This is different from long form notation , which would reference the second employee node as follows:
xmlObject["company"]["employee"][2]
Instead of using company, we use xmlRoot (because it is the document's root node ), and instead of using employee[2], we use xmlChildren[2] (because it is the second child of xmlRoot). There is no array reference after xmlRoot because, like all XML documents, this one has only one root element. The advantage to using long form notation is that it doesn't matter what the name of each individual node is, because nodes are referenced using the xmlChildren array of the parent element. The disadvantage is that now you have to do more work to find out what node is being referenced.The two different notation methods exist for an important reason. Long form notation is like looking at driving directions from MapQuest: The instructions are very detailed but they don't give any perspective on where you are at any given point. In contrast, short form notation is like looking at a map: You can easily see where you are at any given time, but it's not always easy to find out how to get there.You're not limited to using only one method at a time. You can combine both long form and short form, as I'm doing here:
xmlObject.xmlRoot.xmlChildren[2]
Instead of directly referencing the employee array, I'm using xmlChildren.XML Namespaces" for more information.)
xmlObject["company"].xmlChildren[2]["first-name"].xmlText