5,401,186 members and growing! (17,209 online)
Email Password   helpLost your password?
Languages » XML » XSLT     Intermediate

Number To Word Conversion Program using XSLT

By Anand Bolangadi

Number To Word Conversion Program using XSLT
XML, Windows, Dev

Posted: 5 Mar 2002
Updated: 6 Mar 2002
Views: 45,480
Bookmarked: 9 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
4 votes for this Article.
Popularity: 2.84 Rating: 4.71 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
0 votes, 0.0%
4
2 votes, 100.0%
5

Introduction

This is an attempt to write an XSLT generic code to convert a given number to words. This program uses a substantial number of XSLT tags and also XSLT functions showing the power of XSLT programming. Any parser that supports XSLT 1.0 or higher can execute this program. The whole program has not been optimized and is only of an experimental value and cannot be used for any commercial applications.

XSLT Features used

Some main features of the program are:

  • Usage of multiple namespaces. 
  • Self referencing using XSLT function - document()
  • Embedded XML Data which behaves like static arrays in conventional programming languages.
  • Reusable template programming.

Source Code

[Editor Note - String literals had to be broken into two lines to prevent scrolling]

<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
               xmlns:NTW="Number2Word.uri" 
               version="1.0" 
               exclude-result-prefixes="NTW">
<xsl:output method="text" />

<xsl:variable name="ThisDocument" select="document('')"/>
<xsl:template name="NumToWord" match="/">
   <xsl:param name="Number" select="'234567890.55'" />
   <xsl:variable name="RoundedNumber" 
     select="format-number($Number,'#.00')" />
   <xsl:variable name="NumWhole" 
     select="substring-before($RoundedNumber,'.')" />
   <xsl:variable name="DecimalNum" 
     select="substring-after($RoundedNumber,'.')" />
   <xsl:variable name="Base10Num" select="string-length($NumWhole)" />
   <xsl:for-each select="$ThisDocument//NTW:Base10[@BaseLen = $Base10Num]">
      <xsl:if test=
        "string-length(substring($NumWhole,$Base10Num - 12 + 1,3)) > 0">
         <xsl:call-template name="GetWordText">
            <xsl:with-param name="BasePart" 
              select="substring($NumWhole,$Base10Num - 12 + 1,3)" />
            <xsl:with-param name="BaseNumb" select="$Base10Num" />
            <xsl:with-param name="BasePos" select="@BasePos1" />
         </xsl:call-template>
      </xsl:if>
      <xsl:if test=
        "string-length(substring($NumWhole,$Base10Num - 9 + 1,3)) > 0">
         <xsl:call-template name="GetWordText">
            <xsl:with-param name="BasePart" 
               select="substring($NumWhole,$Base10Num - 9 + 1,3)" />
            <xsl:with-param name="BaseNumb" select="$Base10Num" />
            <xsl:with-param name="BasePos" select="@BasePos2" />
         </xsl:call-template>
      </xsl:if>
      <xsl:if test=
         "string-length(substring($NumWhole,$Base10Num - 6 + 1,3)) > 0">
         <xsl:call-template name="GetWordText">
            <xsl:with-param name="BasePart" 
                 select="substring($NumWhole,$Base10Num - 6 + 1,3)" />
            <xsl:with-param name="BaseNumb" select="$Base10Num" />
            <xsl:with-param name="BasePos" select="@BasePos3" />
         </xsl:call-template>
      </xsl:if>
      <xsl:if test=
          "string-length(substring($NumWhole,$Base10Num - 3 + 1,3)) > 2">
         <xsl:call-template name="GetWordText">
            <xsl:with-param name="BasePart" 
               select="substring($NumWhole,$Base10Num - 3 + 1,3)" />
            <xsl:with-param name="BaseNumb" select="3" />
         </xsl:call-template>
      </xsl:if>
      <xsl:if test=
          "2 >= string-length(substring($NumWhole,$Base10Num - 3 + 1,3))">
         <xsl:call-template name="GetWordText">
            <xsl:with-param name="BasePart" 
               select="substring($NumWhole,$Base10Num - 3 + 1,3)" />
            <xsl:with-param name="BaseNumb" select="$Base10Num" />
         </xsl:call-template>
      </xsl:if>
   </xsl:for-each>   
   <xsl:if test="number($DecimalNum) >= 20 or number($DecimalNum) = 10">
      <xsl:value-of select="'and '" />
      <xsl:value-of 
select="$ThisDocument//NTW:Tens[@Num = 
    substring($DecimalNum,1,1) * 10]/@Word" />
      <xsl:value-of 
select="$ThisDocument//NTW:Ones[@Num = 
    substring($DecimalNum,2,2)]/@Word" />
   </xsl:if>
   <xsl:if test="number($DecimalNum) > 10 and 20 > number($DecimalNum)">
      <xsl:value-of select="'and '" />
      <xsl:value-of 
select="$ThisDocument//NTW:Teens[@Num = $DecimalNum]/@Word" />
   </xsl:if>
   <xsl:if test="10 > number($DecimalNum) and number($DecimalNum) > 0">
      <xsl:value-of select="'and '" />
      <xsl:value-of 
select="$ThisDocument//NTW:Ones[@Num = number($DecimalNum)]/@Word" />
   </xsl:if>
</xsl:template>
<xsl:template name="GetWordText">
   <xsl:param name="BasePart" select="''" />
   <xsl:param name="BaseNumb" select="''" />
   <xsl:param name="BasePos" select="''" />
   <xsl:for-each 
select="$ThisDocument//NTW:Base10[@BaseLen = string-length($BasePart)]">
      <xsl:if test="@BasePos4 = 1 and substring($BasePart,1,1) > 0">
         <xsl:value-of 
select="$ThisDocument//NTW:Ones[@Num = substring($BasePart,1,1)]/@Word" />
         <xsl:value-of 
select="$ThisDocument//NTW:BaseName[@BasePlace = 
                string-length($BasePart) - 2]/@Name" />
      </xsl:if>
      <xsl:if test="@BasePos4 = 1 and (substring($BasePart,2,2) >= 20 
                 or substring($BasePart,2,2) = 10)">
         <xsl:value-of select="$ThisDocument//NTW:Tens[@Num = 
                 substring($BasePart,2,1) * 10]/@Word" />
         <xsl:value-of select="$ThisDocument//NTW:Ones[@Num = 
                 substring($BasePart,3,1)]/@Word" />
      </xsl:if>
      <xsl:if test="@BasePos4 = 1 and 
           substring($BasePart,2,2) > 10 and 20 > 
           substring($BasePart,2,2)">
         <xsl:value-of select="$ThisDocument//NTW:Teens[@Num = 
              substring($BasePart,2,2)]/@Word" />
      </xsl:if>
      <xsl:if test="@BasePos4 = 1 and 10 > substring($BasePart,2,2)">
         <xsl:value-of select="$ThisDocument//NTW:Ones[@Num = 
              number(substring($BasePart,3,1))]/@Word" />
      </xsl:if>
      <xsl:if test="@BasePos4 != 1 and 
             (substring($BasePart,1,2) >= 20 or 
              substring($BasePart,1,2) = 10)">
         <xsl:value-of select="$ThisDocument//NTW:Tens[@Num = 
              substring($BasePart,1,1) * 10]/@Word" />
         <xsl:value-of select="$ThisDocument//NTW:Ones[@Num = 
              substring($BasePart,2,1)]/@Word" />
      </xsl:if>
      <xsl:if test="@BasePos4 != 1 and 
              substring($BasePart,1,2) > 10 and 20 > 
              substring($BasePart,1,2)">
         <xsl:value-of select="$ThisDocument//NTW:Teens[@Num = 
              substring($BasePart,1,2)]/@Word" />
      </xsl:if>
      <xsl:if test="@BasePos4 != 1 and 10 > substring($BasePart,1)">
         <xsl:value-of select="$ThisDocument//NTW:Ones[@Num = 
               substring($BasePart,1)]/@Word" />
      </xsl:if>
      </xsl:for-each>
      <xsl:if test="number($BasePart) > 0">
         <xsl:value-of select="$ThisDocument//NTW:BaseName[@BasePlace = 
              $BasePos]/@Name" />
      </xsl:if>
</xsl:template>
<NTW:Ones Num="1" Word="One "/>
<NTW:Ones Num="2" Word="Two "/>
<NTW:Ones Num="3" Word="Three "/>
<NTW:Ones Num="4" Word="Four "/>
<NTW:Ones Num="5" Word="Five "/>
<NTW:Ones Num="6" Word="Six "/>
<NTW:Ones Num="7" Word="Seven "/>
<NTW:Ones Num="8" Word="Eight "/>
<NTW:Ones Num="9" Word="Nine "/>
<NTW:Teens Num="11" Word="Eleven " />
<NTW:Teens Num="12" Word="Twelve " />
<NTW:Teens Num="13" Word="Thirteen " />
<NTW:Teens Num="14" Word="Fourteen " />
<NTW:Teens Num="15" Word="Fifteen " />
<NTW:Teens Num="16" Word="Sixteen " />
<NTW:Teens Num="17" Word="Seventeen " />
<NTW:Teens Num="18" Word="Eighteen " />
<NTW:Teens Num="19" Word="Nineteen " />
<NTW:Tens Num="10" Word="Ten " />
<NTW:Tens Num="20" Word="Twenty " />
<NTW:Tens Num="30" Word="Thirty " />
<NTW:Tens Num="40" Word="Forty " />
<NTW:Tens Num="50" Word="Fifty " />
<NTW:Tens Num="60" Word="Sixty " />
<NTW:Tens Num="70" Word="Seventy " />
<NTW:Tens Num="80" Word="Eighty " />
<NTW:Tens Num="90" Word="Ninety " />
<NTW:BaseName BasePlace="1" Name="Hundred " />
<NTW:BaseName BasePlace="2" Name="Thousand " />
<NTW:BaseName BasePlace="3" Name="Million " />
<NTW:BaseName BasePlace="4" Name="Billion " />
<NTW:Base10 BaseLen="1"  BasePos4="Ones" />
<NTW:Base10 BaseLen="2"  BasePos4="Tens" />
<NTW:Base10 BaseLen="3"  BasePos4="1" />
<NTW:Base10 BaseLen="4"  BasePos3="2" />
<NTW:Base10 BaseLen="5"  BasePos3="2" />
<NTW:Base10 BaseLen="6"  BasePos3="2" />
<NTW:Base10 BaseLen="7"  BasePos2="3" BasePos3="2" />
<NTW:Base10 BaseLen="8"  BasePos2="3" BasePos3="2" />
<NTW:Base10 BaseLen="9"  BasePos2="3" BasePos3="2" />
<NTW:Base10 BaseLen="10" BasePos1="4" BasePos2="3" BasePos3="2" />
<NTW:Base10 BaseLen="11" BasePos1="4" BasePos2="3" BasePos3="2" />
<NTW:Base10 BaseLen="12" BasePos1="4" BasePos2="3" BasePos3="2" />
</xsl:transform>

How to execute this program

  • If you have "msxsl.exe" (can be found on www.microsoft.com), at the MS-DOS command prompt, type: msxsl <XMLFILE> NumToWord.xsl Number=100355.67 where <XMLFILE> is any well-formed XML and Number is the parameter name 
  • If you have "saxon.exe", at the MS-DOS command prompt, type: saxon <XMLFILE> NumToWord.xsl Number=10055.67 where <XMLFILE> is any well-formed XML and Number is the parameter name

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Anand Bolangadi



Occupation: Web Developer
Location: United States United States

Other popular XML articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
  (Refresh) 
Subject  Author Date 
-- There are no messages in this forum --

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 6 Mar 2002
Editor: Nishant Sivakumar
Copyright 2002 by Anand Bolangadi
Everything else Copyright © CodeProject, 1999-2008
Web16 | Advertise on the Code Project