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.
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
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
|
댓글 없음:
댓글 쓰기