UDF: xslt() for CFMX

Posted by Dan on Mar 26, 2003 @ 4:39 PM

I wrote this CFMX-based UDF a while ago, and I thought I'd share it. One of my big gripes about the xslTransform() function in CFMX is that it doesn't support passing parameters to the transformation engine.

Passing parameters can be extremely useful, as it'll allow you to do some conditional operations on in your XSL sheets based upon values determined by the ColdFusion.

In a nutshell, this UDF accomplish this by parsing the XSL stylesheet and looking for instances of the <xsl:param> tag name attributes that match the key in the structure you passed in. Once it's looped through the entire "Params" structure, it'll use the modified XSL stylesheet to do the transformation. Basically, it just temporarily hard codes those values in the param for you.

I've been using the tag for a while and use it in a number of places on my site, but you must take the code as-is. I make no gaurantees it'll work for you!

<!---------------------------------------------------------
User-Defined Function: xslt()

Author:
Dan G. Switzer, II

Date:
01/08/2003

Usage:
xslt(string/xmlObject XmlSource, string XslSource [, struct Params]);

Arguments:
XmlSource: An xml object containing the XML to transform
XslSource: A string containing the XSL stylesheet
Params: A struct containing the key/value pairs to
                        pass to the XSL stylesheet

Version:
2003.01.08
    - First release
---------------------------------------------------------->

<cffunction name="xslt" returnType="string" access="private" output="no">
    <cfargument name="sXml" type="any" required="yes">
    <cfargument name="sXsl" type="string" required="yes">
    <cfargument name="stParams" type="struct" required="no" default="#structNew()#">

    <!---// initialize variables //--->
    <cfset var xXsl = "">
    <cfset var oXslParam = "">
    <cfset var i = "">
    <cfset var j = "">

    <cfscript>
    // if the sXml is either an xml document or an element, convert it to a string
    if( isXmlDoc(sXml) or isXmlElem(sXml) ) sXml = toString(sXml);

    // if there are some parameters, then search for the <xsl:param> tag
    // and replace the content
    if( structCount(stParams) gt 0){
        // convert the stylesheet to an XML document
        xXsl = xmlParse(sXsl);
        // grab all the default param statements into an array
        oXslParam = xmlSearch(xXsl, "/xsl:stylesheet/xsl:param");
        for( i=1; i lte arrayLen(oXslParam); i=i+1 ){
            // if the current param name is in the passed in struct, then alter
            // the default value according to the passed in value
            if( structKeyExists(stParams, oXslParam[i].xmlAttributes.name) ){
                // remove existing "select" arguments
                structDelete(oXslParam[i].xmlAttributes, "select", true);
                // delete existing children elements
                arrayClear(oXslParam[i].xmlChildren);

                // if the value is numeric, insert it as a numeric value
                if( val(stParams[oXslParam[i].xmlAttributes.name]) eq stParams[oXslParam[i].xmlAttributes.name] ){
                    structInsert(oXslParam[i].xmlAttributes, "select", stParams[oXslParam[i].xmlAttributes.name], true);
                // otherwise, treat value as string
                } else {
                    j = arrayLen(oXslParam[i].xmlChildren)+1;
                    oXslParam[i].xmlChildren[j] = xmlElemNew(xXsl, "xsl:text");
                    oXslParam[i].xmlChildren[j].xmlText = toString(stParams[oXslParam[i].xmlAttributes.name]);
                }
            }
        }

        // transform document based on updated XSL document
        return xmlTransform(sXml, toString(xXsl));
    } else {
        // transform as normal
        return xmlTransform(sXml, sXsl);
    }
    
</cfscript>
</cffunction>
Categories: HTML/ColdFusion, Source Code

Comments for this entry have been disabled.