Created
May 10, 2012 14:41
-
-
Save xpathr/2653546 to your computer and use it in GitHub Desktop.
Number To Words by nickdunn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:math="http://exslt.org/math" extension-element-prefixes="exsl math"> | |
| <!-- | |
| Name: Number To Words | |
| Version: 1.0 | |
| Author: Nick Dunn <nick@nick-dunn.co.uk> | |
| URL: http://symphony-cms.com/downloads/xslt/file/20486/ | |
| Parameters: | |
| * number (required) an integer | |
| * resolution (optional) round 'number' to the nearest 'resolution', e.g. '10', '50, '1000' etc. Use '-1' to allow the template to choose an appropriate rounding resolution | |
| * minimum (optional) if the number is less than this the returned string will be 'less than $number' | |
| * maximum (optional) if the number is more than this the returned string will be 'more than $number' | |
| Further usage examples: | |
| http://symphony-cms.com/forum/discussions/763/ | |
| --> | |
| <xsl:template name="number-to-words"> | |
| <xsl:param name="number" /> | |
| <xsl:param name="resolution" /> | |
| <xsl:param name="minimum" /> | |
| <xsl:param name="maximum" /> | |
| <xsl:variable name="words"> | |
| <words> | |
| <word integer="0">zero</word> | |
| <word integer="1">one</word> | |
| <word integer="2">two</word> | |
| <word integer="3">three</word> | |
| <word integer="4">four</word> | |
| <word integer="5">five</word> | |
| <word integer="6">six</word> | |
| <word integer="7">seven</word> | |
| <word integer="8">eight</word> | |
| <word integer="9">nine</word> | |
| <word integer="10">ten</word> | |
| <word integer="11">eleven</word> | |
| <word integer="12">twelve</word> | |
| <word integer="13">thirteen</word> | |
| <word integer="14">fourteen</word> | |
| <word integer="15">fifteen</word> | |
| <word integer="16">sixteen</word> | |
| <word integer="17">seventeen</word> | |
| <word integer="18">eighteen</word> | |
| <word integer="19">nineteen</word> | |
| <word integer="20">twenty</word> | |
| <word integer="30">thirty</word> | |
| <word integer="40">forty</word> | |
| <word integer="50">fifty</word> | |
| <word integer="60">sixty</word> | |
| <word integer="70">seventy</word> | |
| <word integer="80">eighty</word> | |
| <word integer="90">ninety</word> | |
| <word handle="hundred">hundred</word> | |
| <word handle="thousand">thousand</word> | |
| <word handle="million">million</word> | |
| <word handle="less-than">less than</word> | |
| <word handle="more-than">more than</word> | |
| <word handle="about">about</word> | |
| <word handle="and">and</word> | |
| </words> | |
| </xsl:variable> | |
| <xsl:variable name="number-negative"> | |
| <xsl:value-of select="$number < 0"/> | |
| </xsl:variable> | |
| <xsl:variable name="number"> | |
| <xsl:value-of select="math:abs(translate($number,',',''))"/> | |
| </xsl:variable> | |
| <xsl:if test="string(number($number)) != 'NaN'"> | |
| <xsl:variable name="resolved-number"> | |
| <xsl:variable name="auto-resolution"> | |
| <xsl:choose> | |
| <xsl:when test="$resolution = -1"> | |
| <xsl:choose> | |
| <xsl:when test="$number < 20"> | |
| <xsl:text>1</xsl:text> | |
| </xsl:when> | |
| <xsl:when test="$number < 100"> | |
| <xsl:text>5</xsl:text> | |
| </xsl:when> | |
| <xsl:when test="$number < 500"> | |
| <xsl:text>10</xsl:text> | |
| </xsl:when> | |
| <xsl:when test="$number < 1000"> | |
| <xsl:text>50</xsl:text> | |
| </xsl:when> | |
| <xsl:when test="$number < 5000"> | |
| <xsl:text>100</xsl:text> | |
| </xsl:when> | |
| <xsl:when test="$number < 25000"> | |
| <xsl:text>500</xsl:text> | |
| </xsl:when> | |
| <xsl:when test="$number < 100000"> | |
| <xsl:text>1000</xsl:text> | |
| </xsl:when> | |
| <xsl:when test="$number < 500000"> | |
| <xsl:text>5000</xsl:text> | |
| </xsl:when> | |
| <xsl:when test="$number < 1000000"> | |
| <xsl:text>10000</xsl:text> | |
| </xsl:when> | |
| <xsl:when test="$number < 5000000"> | |
| <xsl:text>100000</xsl:text> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:text>1000000</xsl:text> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:value-of select="$resolution"/> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <xsl:choose> | |
| <xsl:when test="$auto-resolution and $auto-resolution <= $number"> | |
| <xsl:variable name="divided" select="$number div $auto-resolution"/> | |
| <xsl:choose> | |
| <xsl:when test="$divided - floor($divided) >= 0.5"> | |
| <xsl:value-of select="ceiling($divided) * $auto-resolution"/> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:value-of select="floor($divided) * $auto-resolution"/> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:text>0</xsl:text> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:variable> | |
| <xsl:choose> | |
| <xsl:when test="$number < $minimum"> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='less-than']"/> | |
| <xsl:text> </xsl:text> | |
| <xsl:call-template name="number-to-words"> | |
| <xsl:with-param name="number" select="$minimum" /> | |
| </xsl:call-template> | |
| </xsl:when> | |
| <xsl:when test="$number > $maximum"> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='more-than']"/> | |
| <xsl:text> </xsl:text> | |
| <xsl:call-template name="number-to-words"> | |
| <xsl:with-param name="number" select="$maximum" /> | |
| </xsl:call-template> | |
| </xsl:when> | |
| <xsl:when test="$resolved-number != 0"> | |
| <xsl:if test="$resolved-number != $number"> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='about']"/> | |
| <xsl:text> </xsl:text> | |
| </xsl:if> | |
| <xsl:if test="$number-negative = 'true'"> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='minus']"/> | |
| <xsl:text> </xsl:text> | |
| </xsl:if> | |
| <xsl:call-template name="number-to-words"> | |
| <xsl:with-param name="number" select="$resolved-number" /> | |
| </xsl:call-template> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:if test="$number-negative = 'true'"> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='minus']"/> | |
| <xsl:text> </xsl:text> | |
| <xsl:call-template name="number-to-words"> | |
| <xsl:with-param name="number" select="$number"/> | |
| </xsl:call-template> | |
| </xsl:if> | |
| <xsl:choose> | |
| <xsl:when test="$number < 21"> | |
| <xsl:value-of select="exsl:node-set($words)//word[@integer = $number]"/> | |
| </xsl:when> | |
| <xsl:when test="$number < 100"> | |
| <xsl:value-of select="exsl:node-set($words)//word[@integer = (10 * floor($number div 10))]"/> | |
| <xsl:variable name="remainder" select="floor($number mod 10)"/> | |
| <xsl:if test="$remainder > 0"> | |
| <xsl:text>-</xsl:text> | |
| <xsl:value-of select="exsl:node-set($words)//word[position() = ($remainder + 1)]"/> | |
| </xsl:if> | |
| </xsl:when> | |
| <xsl:when test="$number < 1000"> | |
| <xsl:value-of select="exsl:node-set($words)//word[@integer = (floor($number div 100))]"/> | |
| <xsl:text> </xsl:text> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='hundred']"/> | |
| <xsl:variable name="remainder" select="floor($number mod 100)"/> | |
| <xsl:if test="$remainder > 0"> | |
| <xsl:text> </xsl:text> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='and']"/> | |
| <xsl:text> </xsl:text> | |
| <xsl:call-template name="number-to-words"> | |
| <xsl:with-param name="number" select="$remainder"/> | |
| </xsl:call-template> | |
| </xsl:if> | |
| </xsl:when> | |
| <xsl:when test="$number < 1000000"> | |
| <xsl:call-template name="number-to-words"> | |
| <xsl:with-param name="number" select="floor($number div 1000)"/> | |
| </xsl:call-template> | |
| <xsl:text> </xsl:text> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='thousand']"/> | |
| <xsl:variable name="remainder" select="floor($number mod 1000)"/> | |
| <xsl:if test="$remainder > 0"> | |
| <xsl:text>, </xsl:text> | |
| <xsl:if test="$remainder < 100"> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='and']"/> | |
| <xsl:text> </xsl:text> | |
| </xsl:if> | |
| <xsl:call-template name="number-to-words"> | |
| <xsl:with-param name="number" select="$remainder"/> | |
| </xsl:call-template> | |
| </xsl:if> | |
| </xsl:when> | |
| <xsl:otherwise> | |
| <xsl:call-template name="number-to-words"> | |
| <xsl:with-param name="number" select="floor($number div 1000000)"/> | |
| </xsl:call-template> | |
| <xsl:text> </xsl:text> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='million']"/> | |
| <xsl:variable name="remainder" select="floor($number mod 1000000)"/> | |
| <xsl:if test="$remainder > 0"> | |
| <xsl:text>, </xsl:text> | |
| <xsl:if test="$remainder < 100"> | |
| <xsl:value-of select="exsl:node-set($words)//word[@handle='and']"/> | |
| <xsl:text> </xsl:text> | |
| </xsl:if> | |
| <xsl:call-template name="number-to-words"> | |
| <xsl:with-param name="number" select="$remainder"/> | |
| </xsl:call-template> | |
| </xsl:if> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:otherwise> | |
| </xsl:choose> | |
| </xsl:if> | |
| </xsl:template> | |
| </xsl:stylesheet> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment