Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
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 Ben Nadel on
Tags: ColdFusion

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.




Reader 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

Reply to this Comment

@Amith,

Do you mean you need to find any tag that has the attribute "IsSSR=true", regardless of the tag name?

Reply to this Comment

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

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.