Получение остатка с помощью XSLT - PullRequest
0 голосов
/ 15 января 2020

Первый раз, когда я напишу, это в 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

ПРИМЕЧАНИЕ: значение пробела 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.

Спасибо за помощь.

1 Ответ

0 голосов
/ 16 января 2020

В 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...