Number To Words
Beautify Digits
Description
Converts an integer to a human-readable string e.g. 123 becomes “one hundred and twenty-three”. Supports minimum/maximum thresholds, rounding, and the ability to auto-round depending on the size of number supplied.
XSLT
View Raw
<?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://www.getsymphony.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://www.getsymphony.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>