Re: [xsl] XPath MOD 10 calculation

Subject: Re: [xsl] XPath MOD 10 calculation
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Thu, 24 May 2007 14:47:12 +0200
Jesper,

I don't know if these UPC codes can have variable length. But if they can, your algorithm should be reversed. That is, the rightmost digit is the first digit (the odd digit).

Note that there are four important differences between the UPC mod10 algorithm and the traditional Luhn mod10 algorithm:

1. Odd and Even digits are reversed (Luhn doubles each even digit, UPC triples each odd digit)
2. UPC does not add individual digits from the result of step 1, instead, it merely add the result
3. UPC triples, where Luhn doubles digits
4. UPC adds a checksum at the rightmost position, which should not be taken into the calculation itself


I believe from looking at your code that 2, 3 and 4 are considered in your code, but 1 is not (esp. not calculated from the right).

Here's a Luhn's algorithm in a single XPath (tested):

sum(for $j in
(for $i in reverse(string-to-codepoints(.))[position() mod 2 = 0] return ($i - 48) * 2,
for $i in reverse(string-to-codepoints(.))[position() mod 2 = 1] return ($i - 48))
return ($j mod 10, $j idiv 10))



Here's UPC's algorithm, based on the above, in a single XPath (*not* tested by lack of testing material and specs):


sum(
for $i in reverse(string-to-codepoints(substring(., 1, string-length(.) - 1))[position() mod 2 = 1] return ($i - 48) * 3,
for $i in reverse(string-to-codepoints(substring(., 1, string-length(.) - 1)))[position() mod 2 = 10 return ($i - 48))
= number(substring(., string-length(.) - 1, 1))



You could consider to put the repeated logic inside a variable, in which case the expression becomes easier:


<xsl:variable name="x" select="for $i in reverse(string-to-codepoints(substring(., 1, string-length(.) - 1)) return $i - 48" />

the XPath then becomes:

   sum(
       for $i in $x[position() mod 2 = 1] return $i * 3,
       for $i in $x[position() mod 2 = 0] return $i,
       = number(substring(., string-length(.) - 1, 1))


Cheers, -- Abel Braaksma


Jesper Tverskov wrote:
On 5/24/07, Abel Braaksma <abel.online@xxxxxxxxx> wrote:

Is yours the same as describe here
http://en.wikipedia.org/wiki/Luhn_algorithm ? Because it seems to me
that your code does not equal that description.

I have until now used this one: http://www.idautomation.com/upceanfaq.html

I have a feeling that I must look into exactly what bar codes are used
these days, before I continue.

Jesper

Current Thread