Skip to main content
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: Sean Roberts
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: Sean Roberts ( @DevelopSean )

Using Variables Into XPath Queries In ColdFusion

By on
Tags:

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.

Want to use code from this post? Check out the license.

Reader Comments

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel