Check XSLT mod for large numbers

I am trying to test module 11 in XSLT 1.0 for a 17 digit number. However, he always seems to give the wrong conclusion.

The only information I could find about this was in this post , but no solution was found.

In the past, I used the XSLT pattern to test Luhn, I understand that this works differently with module checking, but I was wondering if anyone knows about the XSLT pattern that can compute a large number of modules?

+4
source share
2 answers

There is a pure XSLT 1.0 solution that computes $n mod 11 for an integer $n any size :

 <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> 

When this conversion is applied to the following XML document :

 <t>12345678901234567</t> 

the desired correct result is created ( 12345678901234567 mod 11 ) :

 9 

Please note :

  • This solution is easily generalized to calculate $n mod $m for any integer $m - just pass $m as the second parameter.

  • Another generalization is to pass as a parameter a limit above which $n mod $m cannot be directly calculated using the mod operator. This can be useful when using XSLT 2.0 and $n as xs:integer or xs:decimal .

  • Another alternative is to use the Saxon.NET XSLT 2.0 processor or any other XSLT 2.0 processor that implements Big Integer arithmetic. Then the solution is to use the mod operator:

....

 <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> 

When this conversion is applied with Saxon 9.1.07 on the same XML document (above), the same correct result is obtained:

 9 
+3
source

This is because the MSXML type is equivalent to the .NET Double data type, which has an accuracy of 15-16 digits. Try this sample:

 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); 

Output:

 123456789012346000,00 123456789012346000,00 2,00 123456789012345678 123456789012345679 0 

I think you can extend XSLT with C # or JScript because MSXML supports this.

Link: http://msdn.microsoft.com/en-us/library/533texsx(v=VS.100).aspx , http://msdn.microsoft.com/en-us/magazine/cc302079.aspx

+2
source

Source: https://habr.com/ru/post/1390397/


All Articles