[xsl] Small Caps Solution (a bit long)

Subject: [xsl] Small Caps Solution (a bit long)
From: "Jay Bryant" <jay@xxxxxxxxxxxx>
Date: Wed, 1 Sep 2004 19:33:26 -0500
After years of raiding the archive for solutions, I am finally un-lurking
and posting my own solution. I wanted to render a string as small caps
t'other day, but I couldn't find a full solution on the Internet. So, I
rolled my own, and here it is. I have included the XML input and the HTML
output (from Saxon 8). I hope no one minds a fairly lengthy post, as I
wanted to provide full detail.

XML File
------------------------------
<body>
  <heading1>A String to Render in Small Caps</heading1>
</body>
------------------------------

XSL File
------------------------------

<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>
  <xsl:template match="/">
  <html>
    <head>
      <title>Small Cap Test</title>
    </head>
    <style type="text/css">
      .smallCapUpper {
        font-size: Larger
      }
      .smallCapLower
        font-size: Smaller
      }
    </style>
    <body>
      <h1><xsl:apply-templates/></h1>
    </body>
  </html>
  </xsl:template>
  <xsl:template match="heading1">
    <xsl:call-template name="smallCaps">
      <xsl:with-param name="inString" select="."/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="smallCaps">
    <xsl:param name="inString"/>
    <xsl:variable name="firstLetter" select="substring($inString, 1, 1)"/>
    <xsl:variable name="upperFirst" select="translate($firstLetter,
'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
    <xsl:choose>
      <xsl:when test="$firstLetter = $upperFirst">
        <xsl:variable name="lowerTest" select="translate($inString,
'abcdefghijklmnopqrstuvwxyz', '++++++++++++++++++++++++++')"/>
        <xsl:choose>
          <xsl:when test="contains($lowerTest, '+')">
            <xsl:variable name="upperToRemove"
select="substring-before($lowerTest, '+')"/>
            <span class="smallCapUpper"><xsl:value-of
select="$upperToRemove"/></span>
            <xsl:call-template name="smallCaps">
              <xsl:with-param name="inString"
select="substring-after($inString, $upperToRemove)"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise> <!-- test="contains($lowerTest, '+')" -->
            <span class="smallCapUpper"><xsl:value-of
select="$lowerTest"/></span>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:otherwise> <!-- test="$firstLetter = $upperFirst" -->
        <xsl:variable name="upperTest" select="translate($inString,
'ABCDEFGHIJKLMNOPQRSTUVWXYZ', '++++++++++++++++++++++++++')"/>
        <xsl:choose>
          <xsl:when test="contains($upperTest, '+')">
            <xsl:variable name="lowerToRemove"
select="substring-before($upperTest, '+')"/>
            <span class="smallCapLower"><xsl:value-of
select="translate($lowerToRemove, 'abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/></span>
            <xsl:call-template name="smallCaps">
              <xsl:with-param name="inString"
select="substring-after($inString, $lowerToRemove)"/>
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise> <!-- test="contains($upperTest, '+')" -->
            <span class="smallCapLower"><xsl:value-of
select="translate($upperTest, 'abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/></span>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
------------------------------

HTML File
(I modified the actual output a bit so that it would be nicely formatted.
Otherwise, it's a very long line.)
------------------------------
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Small Cap Test</title>
  </head>
  <style type="text/css">
    .smallCapUpper {
      font-size: Larger
    }
    .smallCapLower
      font-size: Smaller
    }
  </style>
  <body>
    <h1>
      <span class="smallCapUpper">A S</span>
      <span class="smallCapLower">TRING TO </span>
      <span class="smallCapUpper">R</span>
      <span class="smallCapLower">ENDER IN </span>
      <span class="smallCapUpper">S</span>
      <span class="smallCapLower">MALL </span>
      <span class="smallCapUpper">C</span>
      <span class="smallCapLower">APS</span>
    </h1>
  </body>
</html>
------------------------------

Jay Bryant
Bryant Communication Services

Current Thread