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  |  Permalink  |  Other Searches  |  Print Page





Reader Comments

Nov 10, 2009 at 2:32 AM // reply »
2 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 »
6,522 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
Nov 24, 2009 at 2:05 AM
Ask Ben: Overriding Core jQuery Methods
But wan't it create problems when we upgrade to more progressive version of the plugin? We would have to analyse all our changes from the beggining before changing the plugin , and if we are talking ... read »
Nov 24, 2009 at 1:46 AM
Ask Ben: Iterating Over An Array With jQuery
Thanks for this! ... read »
Nov 24, 2009 at 1:14 AM
CFContent-Variable Response vs. Standard Output Response
I always thought you took the streamy approach because of some kind of performance gains or reduced server overhead you secretly knew about. Excited for the follow up. ... read »
Nov 24, 2009 at 1:08 AM
Colin Moock's ActionScript 3.0 Event
UGG Women's Metallic Classic UGG Women's Sandra UGG Australia Sandals UGG Classic Mini Boots UGG Lo Pro Classic Tall UGG Nightfall 5359 UGG Roxy Boots UGG Sundance II 5325 UGG Ultra Short UGG Ultra T ... read »
Nov 23, 2009 at 9:27 PM
Using The Apple iPod Shuffle Without iTunes
Does this rename your music and place it automatically? I was just thinking that it would be hard to find and delete songs if it did. ... read »
Nov 23, 2009 at 9:19 PM
Using Contextual SMS Short Code Messages With TextMarks And ColdFusion
Just found this. Great job Ben. I'm new to SMS stuff in general. I'm really interested in how the phone number is matched up to the unique id. Is that a CF thing? Where is that being handled? Maybe ... read »
Nov 23, 2009 at 5:39 PM
My First ColdFusion 8 CFFTP Experience - Rocky But Triumphant
Perhaps this has been mentioned before on your blog but I didn't have luck Googling for it. I just resolved an issue that's pretty trivial but misleading and figured I'd put it here so someone else c ... read »
Nov 23, 2009 at 1:35 PM
jQuery UI 1.7 By Dan Wellman
@Daniel, Definitely not. There's nothing in the first book that is not covered in the second book (in a more up-to-date way). ... read »