Skip to main content
Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.

Using Variables Into XPath Queries In ColdFusion

By Ben Nadel on
Tags: ColdFusion

In ColdFusion 10, xmlSearch() added support for XPath 2.0 syntax and passing variables into XPath queries. Using variables can make the query more readable; but, since XML is case-sensitive, it took me a few minutes to get it working. As such, I figured I'd put together a quick demo on using variables in XPath queries.

When using variables in XPath queries, you reference the variable name by prefixing it with a "$". You can then pass a struct of name-value pairs into xmlSearch() as an optional 3rd argument. But, you have to be careful in how you define that struct. My first attempt looked something like this:

<cfscript>
	// ...
	bestFriends = xmlSearch(
		friends,
		"//friend[ id/text() = $id ]",
		{
			id = 4
		}
	);
	// ...
</cfscript>

Notice that I'm passing in "id" and then referencing it as "$id" in the XPath query. Unfortunately, when I ran this code, I got the following ColdFusion error:

Unable to process the result of the XMLSearch for Undeclared variable in XPath expression: $id. ColdFusion is unable to process the result of the XPath search. You may have an undefined variable in the xpath expression.

After some head-scratching, I realized that it was a case-sensitivity issue. XML is case-sensitive, ColdFusion is not. And, what I forgot would happen behind the scenes is that ColdFusion would silently upper-case my struct keys (making the input case different from the reference case). To fix this, I had to quote the variable names when defining the input struct:

<!--- Define our XML document object. --->
<cfxml variable="friends">

	<friends>
		<friend>
			<id>1</id>
			<name>Joanna</name>
		</friend>
		<friend>
			<id>2</id>
			<name>Tricia</name>
		</friend>
		<friend>
			<id>3</id>
			<name>Sarah</name>
		</friend>
		<friend>
			<id>4</id>
			<name>Kim</name>
		</friend>
	</friends>

</cfxml>

<cfscript>

	// When passing in variables, make sure to !!quote!! the names. XML is case-sensitive
	// and it's important that you explicitly define the case of the variables using quotes;
	// otherwise, ColdFusion may upper-case them, making unavailable in the XPath execution.
	bestFriends = xmlSearch(
		friends,
		"//friend[ ( id/text() = $id ) or contains( $names, name/text() ) ]",
		{
			"id" = 4,
			"names" = "Sarah,Jane,Annie"
		}
	);

	// Collect the names and output the list of resultant friends.
	names = [];

	for ( friend in bestFriends ) {

		arrayAppend( names, friend.name[ 1 ].xmlText );

	}

	writeOutput( "Besties: " & arrayToList( names, ", " ) );

</cfscript>

As you can see, this time, my variable names are quoted. And, when I ran this code, I was able to successfully locate my XML nodes:

Besties: Sarah, Kim

This is a small feature, but a rather nice one. I don't deal with XML much these days; but, it's good to have these tidbits packed away, in the back of my mind, for the occasions that call for some sweet extensible markup language.



Reader Comments