使用 XSLT 获取余数

Getting the Remainder using XSLT

我第一次写这篇文章是在 xslt 中(可以是 xslt 2 或 3)。我需要所有余数的总和。有人遇到过这个吗?谢谢。

这是要求:

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)

我需要获取第一个值 A、B、C、D 而:

    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

注意:space 的值为 20,小数点为“.”是 15.

示例计算

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.

感谢您的帮助。

对于 XSLT 3,一种方法可能是使用累加器:

<?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="&#10;"/>

  <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="&#10;"/>

  <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

当然你只能将代码应用到最后一个元素

  <xsl:template match="fields[last()]">
      <xsl:apply-templates/>
      <xsl:sequence
        select="accumulator-after('remainder-sum')"/>
  </xsl:template>

(而不是之前使用的 <xsl:template match="fields">)。参见 https://xsltfiddle.liberty-development.net/bwe3bG/2