使用 XSLT 的数字到单词转换程序





5.00/5 (2投票s)
2002年3月6日
1分钟阅读

70983

650
使用 XSLT 的数字到单词转换程序
引言
这是一个尝试编写 XSLT 通用代码,将给定的数字转换为文字。该程序使用了大量的 XSLT 标签和 XSLT 函数,展示了 XSLT 编程的强大功能。任何支持 XSLT 1.0 或更高版本的解析器都可以执行此程序。整个程序尚未优化,仅具有实验价值,不能用于任何商业应用。
XSLT 功能
该程序的一些主要特性是:
- 使用多个命名空间
- 使用 XSLT 函数进行自引用 -
document()
- 嵌入式 XML 数据,在传统编程语言中表现为静态数组
- 可重用的模板编程
源代码
[编辑说明 - String
字面量必须分成两行以防止滚动。]
<?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>
如何执行此程序
- 如果您有“msxsl.exe”(可以在 www.microsoft.com 上找到),在 MS-DOS 命令提示符下,输入:
msxsl <XMLFILE> NumToWord.xsl Number=100355.67
,其中<XMLFILE>
是任何格式良好的 XML 文件,而Number
是参数名称。 - 如果您有“saxon.exe”,在 MS-DOS 命令提示符下,输入:
saxon <XMLFILE> NumToWord.xsl Number=10055.67
,其中<XMLFILE>
是任何格式良好的 XML 文件,而Number
是参数名称
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。