Domanda

Sto cercando di fare un controllo di modulo 11 in XSLT 1.0 per un numero di 17 cifre. Tuttavia, sembra sempre di dare l'uscita sbagliata.

L'unica informazione che sono stato in grado di trovare su questo, era in questo post , tuttavia, è stata trovata alcuna soluzione.

Ho in passato utilizzato un modello XSLT per un correttore Luhn, mi rendo conto che questo funziona in modo diverso a un controllo di modulo ma mi chiedevo se qualcuno era a conoscenza di un modello XSLT in grado di calcolare moduluses dei grandi numeri?

È stato utile?

Soluzione

C'è una soluzione pura XSLT 1.0 che calcola $n mod 11 per intero $n di qualsiasi dimensione :

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

Quando si applica questa trasformazione sul seguente documento XML :

<t>12345678901234567</t>

The Wanted risultato corretto (12345678901234567 mod 11) è prodotto :

9

Do nota :

  1. Questa soluzione può essere facilmente generalizzabile a calcolare $n mod $m per qualsiasi $m intero -. Basta passare $m come secondo parametro

  2. Un'altra generalizzazione è di passare come parametro il limite oltre il quale $n mod $m non può essere calcolato direttamente utilizzando l'operatore mod. Questo può essere utile quando si utilizzano XSLT 2.0 e avendo $n sia come xs:integer o xs:decimal.

  3. Un'altra alternativa è quella di utilizzare il processore Saxon.NET XSLT 2.0 o altro processore qualsiasi XSLT 2.0 che implementa Big Integer aritmetica. Quindi la soluzione è solo per utilizzare l'operatore 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>

Quando questa trasformazione viene applicata con Saxon 9.1.07 sullo stesso documento XML (sopra), lo stesso risultato corretto è prodotto:

9

Altri suggerimenti

Questo perché in MSXML tipo numero è equivalente NET Double tipo di dati, che ha precisione 15-16 cifre. Prova questo esempio:

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

Penso che si possa estendere XSLT con C # o JScript, perché MSXML supporta questa.

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top