Skip to main content
Ben Nadel at CFUNITED 2008 (Washington, D.C.) with: Elliott Sprehn
Ben Nadel at CFUNITED 2008 (Washington, D.C.) with: Elliott Sprehn ( @ElliottZ )

Using Multiple Predicates In The Same Part Of An XPath Query In ColdFusion

By on
Tags:

The other day, Will Belden asked me a question about XPath expressions in ColdFusion. Specifically, how to select an XML node based on the existence of multiple child nodes. This seemed like a problem that could be solved using multiple predicates in the same part of the XPath query; but, in the past, I think I've only ever used a single predicate. As such, I wanted to put together a quick demo to make sure that this approach worked as expected.

In XPath, predicates are used to locate a specific node (ex. the 3rd node in a collection) or to locate a node that contains another value (ex. contains a child node called, "ISBN"). A single predicate can contain multiple conditions (using "and" and "or"); but, can that compound expression be broken up into several, individual predicates?

To see this in action, I'm going to find all my friends that love both Movies and Food:

<!--- Build Friends XML document object. --->
<cfxml variable="friends">

	<friends>
		<friend>
			<id>1</id>
			<name>Tricia</name>
			<loves>Movies</loves>
			<loves>Food</loves>
			<loves>Gym</loves>
		</friend>
		<friend>
			<id>2</id>
			<name>Sarah</name>
			<loves>Food</loves>
			<loves>Reading</loves>
		</friend>
		<friend>
			<id>3</id>
			<name>Kim</name>
			<loves>Movies</loves>
			<loves>Art</loves>
			<loves>Food</loves>
		</friend>
	</friends>

</cfxml>


<!---
	Get friends who love food and movies.
	--
	NOTE: This time, we are using an XPath query that defined two predicates on the
	same point in the path.
--->
<cfset bestFriends = xmlSearch(
	friends,
	"//friend[ loves/text() = 'Food' ][ loves/text() = 'Movies' ]/name/text()"
	) />

<cfdump
	var="#bestFriends#"
	label="[ loves/text() = 'Food' ][ loves/text() = 'Movies' ]"
	/>


<br />


<!---
	Get friends who love food and movies.
	--
	NOTE: This time, we are using a single predicate that contains multiple conditions.
--->
<cfset bestFriends = xmlSearch(
	friends,
	"//friend[ ( loves/text() = 'Food' ) and ( loves/text() = 'Movies' ) ]/name/text()"
	) />

<cfdump
	var="#bestFriends#"
	label="[ ( loves/text() = 'Food' ) and ( loves/text() = 'Movies' ) ]"
	/>

Notice that I am trying to execute this search twice - once using multiple predicates and once using a single predicate with multiple conditions. And, when we run this code we get the following page output:

Using multiple predicates in the same part of an XPath query in ColdFusion.

As you can see, both approaches worked and were able to locate the friends that loved movies and food. It seems like the difference might come down to one of personal preference. I find multiple predicates easier to read; but, I also feel like the compound expression might express its intent a bit more clearly. I could go either way on this one.

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

Reader Comments

2 Comments

Hi,

I need Xpath, which will run "n" number of times based on the condition.
for Eg: /a:Charge[//a:IsSSR="true"]/a:Amount
The avobe mentioned will return the Amount where the IsSSR value is true .

But i have multiple tags where IsSSR is true.
so i need to retrieve all the values where IsSSR is true.
Can you please help me out

2 Comments

Actually "isssr" is also one tag in my xml.
I need to find this tag wher ever it is in my xml. Usually we wil have this tag in multiple repetitions. and amount is the other tag which will be with this tag.

So I need to retieve amount tag value wher ever the tag issr is equals to true

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