在现代编程实践中,XSLT(可扩展样式表语言转换)是一种强大的技术,用于将XML文档转换成其他格式,如HTML、文本等。本文将介绍一个使用XSLT将数字转换为文字的程序示例。这个程序展示了XSLT的强大功能,包括使用多个命名空间、自引用函数、嵌入XML数据以及可重用模板编程等。需要注意的是,这个程序目前尚未优化,仅供实验使用,不适用于商业应用。
这个程序的主要特点包括:
以下是程序的源代码,其中包含了一些关键的XSLT标签和函数。为了便于阅读,一些字符串字面量被分成了两行。
<?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>
</xsl:transform>
如果有msxsl.exe
(可以在www.microsoft.com找到),在MS-DOS命令提示符下,输入:
msxsl NumToWord.xsl Number=100355.67
其中<XMLFILE>
是任何格式良好的XML文件,Number是参数名。
如果有saxon.exe
,在MS-DOS命令提示符下,输入:
saxon NumToWord.xsl Number=10055.67