John asked:

Hi Ray,

As I work with XML/ColdFusion more and more, and I'm starting to think that I could make things a lot easier on myself with a better understanding of xpath and xmlSearch(). Currently, when I want to get the text or attributes of a node, I use xmlSearch() to return an array and then I access either result[i].xmlText or result[i].xmlAttributes directly.
Is there a way to tell xmlSearch() to return .xmlText or .xmlAttributes directly?

Good question. I began by creating a super simple XML node that contained both text and attributes.

<cfxml variable="testdoc"> <doc> <header> <author>John Doe</author> </header> <content language="en" charset="iso-8859-1"> </content> </doc> </cfxml>

<cfdump var="#testdoc#">

I've got one simple text field for author and a node, content, that has some attributes. So let's first look at how you can get to the John Doe string via a simple search for author:

<cfset test1 = xmlSearch(testdoc, "//author")> <cfdump var="#test1#">

This will search for author anywhere in the document. The result is:

You can get to the text value by simply adding text():

<cfset test1 = xmlSearch(testdoc, "//author/text()")> <cfdump var="#test1#">

Unfortunately, this still returns a complex structure:

Luckily - W3Schools.com once again comes to the rescue with it's excellent XPath docs. If you go into the functions sections you can see all kinds of interesting things you can do with your searches. One of them - fn:string, will return a string value. You need to dump the fn: portion, but to get the name "John Doe", you can just do:

<cfset test1 = xmlSearch(testdoc, "string(//author/text())")> <cfdump var="#test1#">

Pretty easy, right? You can apply the same thing for a search against the language attribute:

<cfset test1 = xmlSearch(testdoc, "string(//content/@language)")>