Reputation: 75
1st time that i'll be writing this is in xslt (can be xslt 2 or 3). I would need the sum of all remainders. does anyone encountered this already? thank you.
here's the requirement:
2 IDs fields called id1 and id2. Each field has 6 chars (incl. space and decimal)
LEFT ALIGN:
id1: 111 (3 spaces included here after 111)
RIGHT ALIGN:
id2: 123.50 (one decimal here)
I need to get first value A, B, C, D whereas:
VALUE A: add up id1 from position 1 - 3
VALUE B: add up id1 from position 4 - 6
VALUE C: add up id2 from position 1 - 3
VALUE D: add up id2 from position 4 - 6
NOTE: value of space is 20, and decimal '.' is 15.
Sample Computation
id1: 111 (3 spaces included here)
VALUE A: 3 (1+1+1) AND
VALUE B: 60 (20+20+20)
id2: 123.50 (one decimal here)
VALUE C: 5 (1+2+3) AND
VALUE D: 20 (15+5)
Remainder= mod(abs((B+D)-(A+C)),13)
7
Sum of all remainders: 7
Example 2:
Row 1:
LEFT ALIGN:
id1: 111 (3 spaces included here after 111)
RIGHT ALIGN
id2: 123.50
Row 2:
LEFT ALIGN:
id1: 321.50
RIGHT ALIGN
id2: 222 (3 spaces before 111)
Row 1:
Value A: 3 (1+1+1)
Value B: 60 (20+20+20)
Value C: 6 (1+2+3)
Value D: 20 (15+5)
Row 2:
Value A: 6 (3+2+1)
Value B: 20 (15+5)
Value C:60 (20+20+20
Value D: 6 (2+2+2)
Remainder= mod(abs((B+D)-(A+C)),13)
Row1: Remainder = mod(abs((60+20)-(3+6)),13)
Remainder = 6
Row 2:Remainder=mod(abs((20+6)-(6+6)),13)
Remainder = 1
Sum of all remainders: 7 (6+1)
7 or the sum of all remainders will be included in the final output file.
Thanks for the help.
Upvotes: 0
Views: 384
Reputation: 167716
With XSLT 3, one way might be to use accumulators:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="text" item-separator=" "/>
<xsl:mode on-no-match="shallow-skip" use-accumulators="#all"/>
<xsl:accumulator name="A" as="xs:integer?" initial-value="()">
<xsl:accumulator-rule
match="fields/data/id1"
phase="end"
select="accumulator-after('values') => subsequence(1, 3) => sum()"/>
</xsl:accumulator>
<xsl:accumulator name="B" as="xs:integer?" initial-value="()">
<xsl:accumulator-rule
match="fields/data/id1"
phase="end"
select="accumulator-after('values') => subsequence(4, 3) => sum()"/>
</xsl:accumulator>
<xsl:accumulator name="C" as="xs:integer?" initial-value="()">
<xsl:accumulator-rule
match="fields/data/id2"
phase="end"
select="accumulator-after('values') => subsequence(1, 3) => sum()"/>
</xsl:accumulator>
<xsl:accumulator name="D" as="xs:integer?" initial-value="()">
<xsl:accumulator-rule
match="fields/data/id2"
phase="end"
select="accumulator-after('values') => subsequence(4, 3) => sum()"/>
</xsl:accumulator>
<xsl:accumulator name="values" as="xs:integer*" initial-value="()">
<xsl:accumulator-rule
match="data" select="()"/>
<xsl:accumulator-rule
match="data/id1/text() | data/id2/text()"
select="analyze-string(.,'.')//*:match ! (
if (. = '.')
then 15
else if (. = ' ')
then 20
else xs:integer(.))"/>
</xsl:accumulator>
<xsl:accumulator name="remainder" as="xs:integer?" initial-value="()">
<xsl:accumulator-rule
match="fields/data" select="()"/>
<xsl:accumulator-rule
match="fields/data"
phase="end"
select="abs((accumulator-after('B') + accumulator-after('D')) -
(accumulator-after('A') + accumulator-after('C'))) mod 13"/>
</xsl:accumulator>
<xsl:accumulator name="remainder-sum" as="xs:integer?" initial-value="()">
<xsl:accumulator-rule
match="fields" select="0"/>
<xsl:accumulator-rule
match="fields/data"
select="$value + accumulator-after('remainder')"/>
</xsl:accumulator>
<xsl:output method="text" item-separator=" "/>
<xsl:template match="fields">
<xsl:apply-templates/>
<xsl:sequence
select="accumulator-after('remainder-sum')"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bwe3bG/1
Of course you can only apply the code to the last element with
<xsl:template match="fields[last()]">
<xsl:apply-templates/>
<xsl:sequence
select="accumulator-after('remainder-sum')"/>
</xsl:template>
(instead of the <xsl:template match="fields">
used earlier). See https://xsltfiddle.liberty-development.net/bwe3bG/2
Upvotes: 0