我正在尝试在XSLT 1.0中对17位数进行模数11检查。但是,它似乎总是给出错误的输出。
我能找到的唯一信息是this post,但是没有找到解决方案。
我过去曾使用XSLT模板作为Luhn检查程序,我意识到这与模数检查的工作方式不同,但我想知道是否有人知道可以计算大数模的XSLT模板?
答案 0 :(得分:3)
有一个纯XSLT 1.0解决方案可以计算$n mod 11
任意大小的$n
:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:call-template name="mod11"/>
</xsl:template>
<xsl:template name="mod11">
<xsl:param name="pN" select="."/>
<xsl:choose>
<xsl:when test="not($pN > 9999999999999999)">
<xsl:value-of select="$pN mod 11"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vLen" select="string-length($pN)"/>
<xsl:variable name="vLen1" select="$vLen -1"/>
<xsl:variable name="vPart1" select=
"substring($pN, 1, $vLen1)"/>
<xsl:variable name="vPart2" select=
"substring($pN, $vLen1 +1)"/>
<xsl:variable name="vMod1">
<xsl:call-template name="mod11">
<xsl:with-param name="pN" select="$vPart1"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vMod2" select="$vPart2 mod 11"/>
<xsl:value-of select="(10*$vMod1 + $vMod2) mod 11"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
将此转换应用于以下XML文档:
<t>12345678901234567</t>
生成所需的正确结果(12345678901234567 mod 11
):
9
请注意:
此解决方案可以很容易地推广到任何整数$n mod $m
计算$m
- 只需将$m
作为第二个参数传递。
另一个概括是将参数作为参数传递给上面的$n mod $m
无法使用mod
运算符直接计算。在使用XSLT 2.0并将$n
作为xs:integer
或xs:decimal
时,此功能非常有用。
另一种方法是使用Saxon.NET XSLT 2.0处理器或任何其他实现Big Integer算术的XSLT 2.0处理器。然后解决方案就是使用mod
运算符:
...
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:value-of select="xs:integer(.) mod 11"/>
</xsl:template>
</xsl:stylesheet>
当在同一个XML文档(上面)中使用Saxon 9.1.07进行此转换时,会产生相同的正确结果:
9
答案 1 :(得分:2)
这是因为在MSXML中,数字类型等同于.NET Double
数据类型,其精度为15-16位。
试试这个样本:
double d = 123456789012345678;
Console.WriteLine("{0:f}", d);
Console.WriteLine("{0:f}", d + 1);
Console.WriteLine("{0:f}", d % 3);
long l = 123456789012345678;
Console.WriteLine(l);
Console.WriteLine(l + 1);
Console.WriteLine(l % 3);
输出:
123456789012346000,00
123456789012346000,00
2,00
123456789012345678
123456789012345679
0
我认为您可以使用C#或JScript扩展XSLT,因为MSXML支持此功能。
参考:http://msdn.microsoft.com/en-us/library/533texsx(v=VS.100).aspx,http://msdn.microsoft.com/en-us/magazine/cc302079.aspx