Re: [xsl] XPath MOD 10 calculation

Subject: Re: [xsl] XPath MOD 10 calculation
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Thu, 24 May 2007 13:37:54 +0200
Well, 'elegant' is in the eye of the beholder, I think ;)

Perhaps this is something that you consider more elegant. But depending on your audience, it may win the beauty contest, but not receive praise for elegance:

<xsl:variable name="x"
select="sum(for $i in (1,3,5,7,9,11,2,4,6,8,10) return number(substring(., $i, 1))) mod 10" />


and leave the xsl:if as-is. Or you can rewrite your xsl:if like this:

<xsl:if test="(10 - $x) mod 10 ne substring(., 12, 1)" />

which brings us to a possibility to combine the two in one expression without repetition:

<xsl:if test="(10 - sum(for $i in (1,3,5,7,9,11,2,4,6,8,10) return number(substring(., $i, 1))) mod 10) mod 10 ne substring(., 12, 1)" />


I'm not certain of the order of operator precedence, you may have to insert some parentheses here and there. I didn't test it, because I don't know the MOD 10 algorithm and you did not provide enough examples to really test it. I chose for number() instead of xs:integer because sum() takes doubles and xs:integer can fail with an error, where number() cannot fail.


Cheers,
-- Abel Braaksma





Jesper Tverskov wrote:
Hi list

I have made a MOD 10 calculation with XPath to check if a UPC barcode
number is legal. I am just wondering if the code could be made more
elegant with some of the new stuff in XPath 2.0.

Since I am going to use the test in Schematron, I can use variables
but not templates or other xsl elements than shown below.

The context value is some UPC code like 639382000393.

<xsl:variable name="x" select="((xs:integer(substring(., 1, 1)) +
xs:integer(substring(., 3, 1)) + xs:integer(substring(., 5, 1)) +
xs:integer(substring(., 7, 1)) + xs:integer(substring(., 9, 1)) +
xs:integer(substring(., 11, 1))) * 3 + (xs:integer(substring(., 2, 1))
+ xs:integer(substring(., 4, 1)) + xs:integer(substring(., 6, 1)) +
xs:integer(substring(., 8, 1)) + xs:integer(substring(., 10, 1)))) mod
10"/>

<xsl:if test="(if ($x ne 0) then (10 - $x) else $x) ne
xs:integer(substring(., 12, 1))">
<!-- Not legal, do something -->
</xsl:if>

Cheers,

Jesper Tverskov
http://www.xmlplease.com/xslt

Current Thread