Patty
Patty

Reputation: 531

XSLT - Capitalize first letter only but how to handle names like McDermott

I have used below code to capitalize first letter only but dont want to convert McDermott to Mcdermott. How can exceptions like this be handled in the code?

<xsl:variable name="lowers" select='"abcdefghijklmnopqrstuvwxyz"'/>
    <xsl:variable name="uppers" select='"ABCDEFGHIJKLMNOPQRSTUVWXYZ"'/>
    <xsl:variable name="numeric" select="0123456789"/>
    <xsl:variable name="alpha-numeric" select="concat($lowers,$uppers,$numeric)"/>
    <xsl:template name="capitalize">
        <xsl:param name="val"/>
        <xsl:param name="alphanumeric-seen" select="false()"/>
        <xsl:variable name="head" select="substring($val, 1, 1)"/>
        <xsl:if test="$head">
            <xsl:variable name="is-alpha-numeric" select="not(translate($head, $alpha-numeric, ''))"/>
            <xsl:variable name="tail" select="substring($val, 2)"/>
            <xsl:choose>
                <xsl:when test="$is-alpha-numeric">
                    <xsl:choose>
                        <xsl:when test="$alphanumeric-seen">
                            <xsl:value-of select="$head"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:value-of select="translate($head, $lowers, $uppers)"/>
                        </xsl:otherwise>
                    </xsl:choose>
                    <xsl:call-template name="capitalize">
                        <xsl:with-param name="val" select="translate($tail, $uppers, $lowers)"/>
                        <xsl:with-param name="alphanumeric-seen" select="true()"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$head"/>
                    <xsl:call-template name="capitalize">
                        <xsl:with-param name="val" select="translate($tail, $uppers, $lowers)"/>
                        <xsl:with-param name="alphanumeric-seen" select="false()"/>
                    </xsl:call-template>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:if>
    </xsl:template>

Upvotes: 1

Views: 98

Answers (1)

Siebe Jongebloed
Siebe Jongebloed

Reputation: 4869

To give you a direction use this xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  version="1.0"
  >
  <xsl:output indent="yes"/>
  <xsl:variable name="lowers" select='"abcdefghijklmnopqrstuvwxyz"'/>
  <xsl:variable name="uppers" select='"ABCDEFGHIJKLMNOPQRSTUVWXYZ"'/>
  <xsl:variable name="numeric" select="0123456789"/>
  
  <xsl:template match="/names">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
    
  <xsl:template match="name">
    <xsl:variable name="orgLength"              select="string-length(.)"/>
    <xsl:variable name="allLowersSkipt"         select="translate(.,$lowers,'')"/>
    <xsl:variable name="allUppersSkipt"         select="translate(.,$uppers,'')"/>
    <xsl:variable name="allNumericSkiptLength"  select="string-length(translate(.,$numeric,''))"/>
    <xsl:variable name="allUppersSkiptLength"   select="string-length($allUppersSkipt)"/>
    <xsl:variable name="allLowersSkiptLength"   select="string-length($allLowersSkipt)"/>
    <xsl:variable name="firstCapital"           select="concat(translate(substring(.,1,1),$lowers,$uppers),translate(substring(.,2),$uppers,$lowers))"/>

    <xsl:copy>
      <xsl:comment>Org: <xsl:value-of select="."/></xsl:comment>
      <xsl:choose>
        <xsl:when test="$allNumericSkiptLength!=$orgLength">
          <xsl:comment>Contains Number</xsl:comment>
          <xsl:value-of select="."/>
        </xsl:when>
        <xsl:when test="$firstCapital=.">
          <xsl:comment>Already Correct</xsl:comment>
          <xsl:value-of select="."/>
        </xsl:when>
        <xsl:when test="$allUppersSkiptLength=0">
          <xsl:comment>All Uppers</xsl:comment>
          <xsl:value-of select="$firstCapital"/>
        </xsl:when>
        <xsl:when test="$allLowersSkiptLength=0">
          <xsl:comment>All Lowers</xsl:comment>
          <xsl:value-of select="$firstCapital"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:comment>Contains a combination of Lowers and Uppers</xsl:comment>
          <xsl:value-of select="."/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

When used on this xml:

<?xml version="1.0" encoding="UTF-8"?>
<names>
  <name>MacDonaldMet1</name>
  <name>McDermott</name>
  <name>ALLCAPITAL</name>
  <name>alllower</name>
  <name>Firstcapital</name>
  <name>MacDonald</name>
</names>

Gives this result:

<?xml version="1.0" encoding="UTF-8"?>
<names>
   <name><!--Org: MacDonaldMet1--><!--Contains Number-->MacDonaldMet1</name>
   <name><!--Org: McDermott--><!--Contains a combination of Lowers and Uppers-->McDermott</name>
   <name><!--Org: ALLCAPITAL--><!--All Uppers-->Allcapital</name>
   <name><!--Org: alllower--><!--All Lowers-->Alllower</name>
   <name><!--Org: Firstcapital--><!--Already Correct-->Firstcapital</name>
   <name><!--Org: MacDonald--><!--Contains a combination of Lowers and Uppers-->MacDonald</name>
</names>

Upvotes: 1

Related Questions