XSLT

Page  1  |  2  |  3  |- 4 - 

   
Constants and Variables

 

There is an XSLT element called - xsl:variable. But it's a variable constant, that once set, can't be changed. The way one operates on a variable is by way of recursive calls to the templates that use the xsl:param and xsl:with-param elements. These variables and parameters, once defined, and then referred to with a dollar sign - such as, $variable1.

Here's an example:

<xsl:template name="TableAttr">
    <xsl:param name="codes"/>
    <xsl:call-template name="LoopAttr">
       <xsl:with-param name="codes" select="$codes"/>
       <xsl:with-param name="attr">border,width,height,bgcolor,cellpadding,cellspacing,class,</xsl:with-param>
       <xsl:with-param name="dfalt">0,,,#D7D7D7,2,0,,</xsl:with-param>
    </xsl:call-template>
</xsl:template>
 

 
<xsl:template name="LoopAttr">
    <xsl:param name="codes"/>
    <xsl:param name="attr"/>
    <xsl:param name="dfalt"/>
 
    <xsl:if test="string-length($attr) > 1 " >
       <xsl:variable name="attrName"><xsl:value-of select="substring-before($attr,',')"/></xsl:variable>
       <xsl:variable name="nextCodeData">
          <xsl:value-of select="normalize-space(substring-before($codes,','))"/>
       </xsl:variable>
 
      <xsl:choose>
          <xsl:when test="starts-with($nextCodeData,$attrName)">
             <xsl:variable name="attrVal">
             <xsl:value-of select="substring-after($nextCodeData,'=')"/></xsl:variable>             
             <xsl:if test="string-length($attrVal)>0">
                <xsl:attribute name="{$attrName}"><xsl:value-of select="$attrVal"/></xsl:attribute>
             </xsl:if>
          </xsl:when>
          <xsl:otherwise>
             <xsl:variable name="attrVal"><xsl:value-of select="substring-before($dfalt,',')"/></xsl:variable>
             <xsl:if test="string-length($attrVal)>0">
                <xsl:attribute name="{$attrName}"><xsl:value-of select="$attrVal"/></xsl:attribute>
             </xsl:if>
          </xsl:otherwise>
       </xsl:choose>
 
       <xsl:call-template name="LoopAttr">
          <xsl:with-param name="codes">
             <xsl:choose>
                <xsl:when test="starts-with($nextCodeData,$attrName)">
                   <xsl:value-of select="substring-after($codes,',')"/>
                </xsl:when>
                <xsl:otherwise><xsl:value-of select="$codes"/></xsl:otherwise>
             </xsl:choose>
          </xsl:with-param>
          <xsl:with-param name="attr" select="substring-after($attr,',')"/>
          <xsl:with-param name="dfalt" select="substring-after($dfalt,',')"/>
       </xsl:call-template>
    </xsl:if>
</xsl:template>

 
 
Example - Create HTML Table Tag

 

The TableAttr template can be in one of your library, 'included', xsl programs. And the TableAttr template can be called using the XSLT element - xsl:call-template:

<!-- up at the top of the XSLT document -->
<xsl:variable name="body_bgcolor"><xsl:value-of select="//body/bgcolor"/></xsl:variable>
 
<!-- somewhere further down -->
<xsl:element name="table">
    <xsl:call-template name="TableAttr">
      <xsl:with-param name="codes">
          bgcolor=<xsl:value-of select="$body_bgcolor"/>,cellpadding=6,
       </xsl:with-param>
   </xsl:call-template>
 
    <tr><td>
       <font size="+2" face="Arial,Helvetica">HELLO!</font>
    </td></tr>
</xsl:element>

 

Called in this way, the TableAttr template is used to build up attributes for a HTML TABLE tag. Defaults are also provided and then the core procedure/template, LoopAttr, is called. You can see that in calling TableAttr those defaults can be overridden by using the attribute name, an equals sign, and a value. If that particular attribute isn't specified, then the default given in TableAttr will be used, instead. The defaults are also treated as 'validation' in the sense that only those table attributes listed in the default can be specified in the override string - no others. Also, in this template/procedure, it's required that any override string is terminated with a comma, as shown. So there's a comma after "cellpadding=6". In this case, the bgcolor might be needed for various templates and a 'global' variable/constant was used at the top of the XSLT. Let's just arbitrarily say that $body_bgcolor = "#EFEFD0" (the pound sign isn't added in the template, so has to be part of the data value). This specific call, then, will give you an HTML:

 
<table border="0" bgcolor="#EFEFD0" cellpadding="6" cellspacing="0"><tr>
    <td>
       <font size="+2" face="Arial,Helvetica">HELLO!</font>
    </td>
</tr></table>

 
 
Variables (recursion)

 

It was said that XSLT is a 'declarative' programming language. The 'variables' are really constants. And parameters are used, recursively, as variables. Look at:

<xsl:call-template name="LoopAttr">
    <xsl:with-param name="attr" select="substring-after($attr,',')"/>

 

You can see that this is part of a call to the same template - LoopAttr - in which this is contained. It's calling itself, and also keeping track of the old values, from previous calls, of the specified parameters. That keeping track makes it - recursive. If it didn't, it would just be - reentrant. So this attr parameter/variable is being modified each time LoopAttr is called, from within LoopAttr. It's being modified with yet another built-in XSLT function, a handy substring function - substring-after(). Very simply, it's returning the right() substring, in essence, everything to the right in attr following the first comma encountered. So attr is being pared down, field by field, left to right, each time LoopAttr is called from here, until there's nothing left in attr. The leading xsl:if that tests the string length of attr is what terminates the recursive calls to LoopAttr. When attr is down to nothing, LoopAttr, at that point, just stops and quickly winds back out.

 
<xsl:value-of select="normalize-space(substring-before($codes,','))"/>

 

This is where the value for the nextCodeData variable/constant is set. It uses another built-in function - normalize-space(). This trims all leading and trailing spaces. It then also replaces any string of multiple spaces with just one space. That's just handy in case you want to call the templates, but including some spaces for readability in the override string. The substring-before() function is similar to the after function, just mentioned, but that it returns everything to the left of the first instance of the comparison string, in this case, again, a single comma. So nextCodeData simply is the leftmost field of the override string, equals sign and all. And, similarly, attrName is the first field in the list of default table attributes.

The xsl:choose section, again really an if-then-else control structure, is testing if the next default table attribute is, in fact, the leftmost field in any override string. If it is, then that override value will be used, instead, and the override string will be pared down, left to right, in the xsl:call-template, following. In both cases, a further test is made to see if there's any actual value. If not, in either case, then that attribute is not added to the table element in the HTML output.


 
 More to read:

ZVON XSLT by example
O'Reilly XML.com Intro to XSLT
W3 Schools W3schools article on XSLT
Inet.com Article on XSLT
TopXML Overview Overview of XSLT
TopXML XSLT Tutorial
Lycos WebMonkey Jay Greenspan Tutorial
Dave Pawson Given understanding of XSLT basics, more in-depth
TOP XML XSLT and ASP
ASPX More XSLT and ASP
Objects by Design XSLT keys
Jeni Tennison XSLT Pages (from W3C XSL WG member)
Jeni Tennison Explaining the XSLT Meunchian grouping method
EXSLT Some of Tennison's (and others) XSLT extensions (w/o using msxsl:script)
Microsoft Help Microsoft's original compiled help file for msxml 4.0, with XSLT reference (click: download de SDK)
(Robin) Cover Pages Cover's XSLT links
W3C XSLT WWW Consortium XSLT spec