XSLT1.0で17桁の数値のモジュラス11チェックを実行しようとしています。ただし、常に間違った出力を与えるようです。
これについて私が見つけた唯一の情報はこの投稿にありましたが、解決策は見つかりませんでした。
過去にLuhnチェッカーにXSLTテンプレートを使用したことがありますが、これはモジュラスチェックとは異なる動作をすることに気付きましたが、多数のモジュラスを計算できるXSLTテンプレートを知っている人はいないでしょうか。
任意のサイズ$n mod 11
の整数を計算する純粋なXSLT1.0ソリューションがあります $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
このソリューションは、任意の整数を計算するために簡単に一般化できます。2番目のパラメーターとして$m
渡すだけです。$m
もう1つの一般化は、演算子$n mod $m
を使用して直接計算できない上記の制限をパラメーターとして渡すことです。これは、XSLT 2.0を使用していて、またはのいずれかをmod
使用している場合に役立ちます。$n
xs:integer
xs:decimal
もう1つの方法は、Saxon.NETXSLT2.0プロセッサまたはBigInteger演算を実装するその他のXSLT2.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
これは、MSXMLの数値型はDouble
、15〜16桁の精度を持つ.NETデータ型と同等であるためです。このサンプルを試してください:
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
MSXMLはこれをサポートしているので、C#またはJScriptを使用してXSLTを拡張できると思います。
参照: http: //msdn.microsoft.com/en-us/library/533texsx (v = VS.100).aspx 、 http: //msdn.microsoft.com/en-us/magazine/cc302079.aspx