XSLT Case Conversion Solution
The following article was written by Erich
Von Hauske N. after a discussion on XSLTalk. Corey
Haines started a tread on how to do recursion in XSLT, which lead to this
solution that Erich and Corey came up with.
Download the source
The solution of a problem like case conversion can take many forms,
especially when you use a language like XSLT, which gives you the flexibility
to give many solutions; each one with a different degree of
recursiveness. The solution presented in this document is a middle-ground
solution, it's recursive, but not as recursive as it could get, nevertheless it
has a better performance than the completely recursive solution.
What we are demonstrating is firstly how to convert your XML data from on
case to another. As XML is case sensitive, when you need to do searches on
your data, using the translate function demonstrated enables
case-insensitive searches. Then we are demonstrating a solution for
implementing proper case converting - which demonstrates the recursion.
Upper Case Transformation
Upper and lower case transformations are very easy in XSLT thanks to the translate function. An
alternative solution could be to implement the transformation and switch character by character, but since XSLT already
gives us a better solution, let's better take advantage of it. Please find
the full source in the downloadable file.
Firstly lets place all the letters of the alphabet, lower case and upper case
in variables.
<xsl:variable name="lcletters">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name="ucletters">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
To then convert our data to upper case we use the translate method, which
replaces all the lower case characters with upper case.
<xsl:value-of select="translate($toconvert,$lcletters,$ucletters)"/>
Lower Case Transformation
The lower case transformation is basically the same:
<xsl:value-of select="translate($toconvert,$ucletters,$lcletters)"/>
Proper Case Transformation
The interesting part of this exercise is really in here: the proper case transformation. The presented solution first translates the entire string to
lower case, and after that it translate only the first letter of
every word to upper case. Here's the code:
<xsl:template name='convertpropercase'>
<xsl:param name='toconvert' />
<xsl:if test="string-length($toconvert) > 0">
<xsl:variable name='f' select='substring($toconvert, 1, 1)' />
<xsl:variable name='s' select='substring($toconvert, 2)' />
<xsl:call-template name='convertcase'>
<xsl:with-param name='toconvert' select='$f' />
<xsl:with-param name='conversion'>upper</xsl:with-param>
</xsl:call-template>
<xsl:choose>
<xsl:when test="contains($s,' ')">
<xsl:value-of select='substring-before($s," ")'/>
<xsl:text> </xsl:text>
<xsl:call-template name='convertpropercase'>
<xsl:with-param name='toconvert' select='substring-after($s," ")' />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select='$s'/>
</xsl:otherwise>
</xsl:choose>bv
</xsl:if>
</xsl:template>
Basically what it does is to check if the string to
covert has characters (end condition for recursion), and if it has characters
then it breaks the string in two parts: the first letter and the rest of the
string, converts the first letter to upper case and checks if the rest of the
string contains spaces (word separators), if it contains spaces then it outputs
the rest of the current word (substring-before($s," ")) and calls the
convertpropercase template with the rest of the string ('substring-after($s,"
")') to convert the rest of the words to proper case.
Procedural Programming in XSLT
If you were wondering what the xsl:call-template element does, it allows one to use functions in XSLT, where basically you can call
a template from anywhere in the XSLT. You pass the template parameters,
like you do in functions. Instead of the template having a matching
element, you give it a name. (<xsl:template name='convertpropercase'>)
Declaring the template:
<xsl:template name='convertcase'>
<xsl:param name='toconvert' />
<xsl:param name='conversion' />
....
</xsl:template>
Calling the template:
<xsl:call-template name='convertcase'>
<xsl:with-param name='toconvert' select='$f' />
<xsl:with-param name='conversion'>upper</xsl:with-param>
</xsl:call-template>
|
View the Source
|
 |
|