Ask Ben: Selecting Node Attributes In XSLT Based On List Values In ColdFusion

Posted November 9, 2009 at 10:02 AM

Tags: ColdFusion, Ask Ben

Ben, do you know how to check to see if a xml attribute is in a list? I'm looking at the contains() function, but I'm not sure of the correct syntax or if there is a better way, but I cant seem to get this to work. I don't know how to reference the value of the @system as the second argument of the contains. Can I used something like 'this' (minus quotes). Also, I have yet to really find a way to use variables in the match and selects of an xsl file. I've read some things on using another namespace and then using a node-set() function (until cf handles xslt 2.0)?

As you are probably finding out, ColdFusion's current implementation of XSLT is somewhat limited. If you take the list of XSLT and XPath functions listed on the web and try to get them to work in a ColdFusion XML transformation, you'll quickly find out that many of them are not supported. One that does work however, as you mentioned, is the contains() function. As we have seen before, though, this method is case sensitive; as such, you have to make sure that the values used with this function are strictly formatted.

With the contains() function, the first argument is the source value and the second argument is the substring for which you are testing. As such, calling:

contains( 'benjamin', 'ben' )

... would return True as the string "ben" is contained within the source string, "benjamin." Notice, however, that this is not using any sense of value deliniation - it's a substring or it isn't. When doing simple tests, this is not a problem; but, when you are dealing with lists of values, you run the risk of getting a false positive. To help compensate for this, we can add our own delimiters to the list and then make sure our substring also contains those delimiters:

contains( '-benjamin-', concat( '-', 'ben', '-' ) )

This time, the contains() function call would return False since the value, "-ben-" is no longer a substring of the source value, "-benjamin-."

NOTE: XSLT and XPath have list-based functions, but they are not supported by ColdFusion's current XSLT engine.

With that in mind, let's take a look at a small example:

 Launch code in new window » Download code as text file »

  • <!--- Create our XML data. --->
  • <cfxml variable="girls">
  •  
  • <girls>
  • <girl type="cute">
  • <name>Sarah</name>
  • </girl>
  • <girl type="athletic">
  • <name>Tricia</name>
  • </girl>
  • <girl type="hot">
  • <name>Katie</name>
  • </girl>
  • <girl type="cute">
  • <name>Libby</name>
  • </girl>
  • </girls>
  •  
  • </cfxml>
  •  
  •  
  • <!--- Create the XSL tranformation. --->
  • <cfsavecontent variable="xslt">
  •  
  • <!--- Document type declaration. --->
  • <?xml version="1.0" encoding="ISO-8859-1"?>
  •  
  • <!--- Define the transformation. --->
  • <xsl:transform
  • version="1.0"
  • xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  •  
  •  
  • <!--- Match the root girls node. --->
  • <xsl:template match="/girls">
  •  
  • <girls>
  •  
  • <!---
  • Copy each GIRL node if the TYPE attribute
  • is contained within the given list: hot or
  • athletic.
  •  
  • NOTE: We are wrapping the TYPE attribute in
  • list delimiters to cut down on the chance of
  • a substring giving us a false positive.
  • --->
  • <xsl:copy-of
  • select="./girl[ contains( '-hot-athletic-', concat( '-', @type, '-' ) ) ]"
  • />
  •  
  • </girls>
  •  
  • </xsl:template>
  •  
  • </xsl:transform>
  •  
  • </cfsavecontent>
  •  
  •  
  • <!--- Transform the document. --->
  • <cfset newGirls = xmlParse(
  • xmlTransform( girls, trim( xslt ) )
  • ) />
  •  
  • <!--- Output the new girls. --->
  • <cfdump
  • var="#newGirls#"
  • label="Hot Girls"
  • />

Here, we are creating an XML document of girl nodes and then transforming it into another XML document that contains only girls that are "hot" or "athletic". And, as you can see, the filtering of the girl nodes is done using the following contains() function call:

contains( '-hot-athletic-', concat( '-', @type, '-' ) )

Each value in our list is wrapped in a delimiter to help prevent false positive. And, when we run this code, we get the following output:

 
 
 
 
 
 
Working With Lists In ColdFusion XSLT. 
 
 
 

As you can see, this worked nicely. As a note on this, when you are in the middle of a "select" statement, the "this" reference is implied as the node currently being examined. As such, within our contains() function call, the attribute reference "@type" correctly references the attribute of the current "girl" node being collected.

I hope this points you in the right direction. You mentioned in your question the EXSL extension library. I have never heard of this, but I just did a bit of experimentation with the node-set() method and it seems very interesting. I'll probably follow up with another blog post on that topic shortly.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Other Searches  |  Print Page





Reader Comments

Nov 10, 2009 at 2:32 AM // reply »
4 Comments

Ben!

I tried the code.working fine. very interesting.
Its cute n hot:)

Keep Rocking

Thanks,
Raghuram Reddy Gottimukkula
http://raghuramcoldfusion.blogspot.com/
Adobe Certified Coldfusion Developer
Bangalore India


Nov 10, 2009 at 7:57 AM // reply »
7,572 Comments

@Raghuram,

Thanks! The person asking the question actually brought up a library that I knew nothing about; I'll try to write up something about it today or tomorrow as a follow-up.


Post Comment  |  Ask Ben

Recent Blog Comments
Mar 21, 2010 at 11:13 AM
A New Wrist Pain
@chiropractor suwanee, Spoken like someone trying to sell something. Other than for minor, temporary relief from some back pain, chiropractic treatment is nothing but placebo effect and quackery. ... read »
Mar 21, 2010 at 6:32 AM
ColdFusion CFPOP - My First Look
Apologies... The field name in the db for C. is "BounceCode" It stores the code / message which is returned in the email. Sorry for the confusion. ... read »
Mar 21, 2010 at 6:29 AM
ColdFusion CFPOP - My First Look
@Jose Galdamez, Hi Ben and Jose 1st of all.. big thanks to Jose for his Skype chat a few weeks back. Your time was much appreciated. I have come up with a rather unelegant solution to my problem a ... read »
Mar 21, 2010 at 3:42 AM
A New Wrist Pain
Chiropractic treatment is one of the best methods for treating numerous health problems naturally. After years of experience being a chiropractor, I have found that it is a powerful way to solve many ... read »
Mar 20, 2010 at 12:07 PM
Drawing On The iPhone Canvas With jQuery And ColdFusion
Simply awesome. Saved my day. ... read »
Mar 20, 2010 at 9:00 AM
Building A Fixed-Position Bottom Menu Bar (ala FaceBook)
I would like to say thx for an easy way to create a bottom bar. I do have a ?. Is it possible to center the bar if i want to resize it to ex 85%. Regards Offenbach ... read »
Mar 19, 2010 at 7:26 PM
MySQL 3/4 - com.mysql.jdbc.Driver And allowMultiQueries=true
Thank you very much for this post. Adding allowMultiQueries="true" in context.xml didn't help until I added it to url as allowMultiQueries=true Good idea is to use prepared statements and it will he ... read »
Jim
Mar 19, 2010 at 4:49 PM
Nobody Puts Baby In The Corner!
Wow. This is like suddenly finding a support group for your secret shame. I'm not alone! I always liked this movie, even though it is extremely cheesy. I just wish Jennifer Grey hadn't gotten the ... read »