Текущий итог с вычисленными переменными xsl:? - PullRequest
0 голосов
/ 06 августа 2020

Моя бухгалтерия - XML содержит два отдельных элемента, один только для положительной, а другой для отрицательной денежной стоимости. Я хочу создать HTML -таблицу с использованием XSL для входящей и исходящей передачи, а также промежуточную сумму для каждой строки. Я нашел sum(preceding-sibling::Buchungszeile/Betrag) + Betrag), который отлично работает, если все элементы содержат число. К сожалению, для положительных значений отрицательный элемент не равен 0, а пуст, и наоборот.

<Buchungszeile>
  <Buchungstag>2019-12-05</Buchungstag>
  <Soll-Betrag>100</Soll-Betrag>
  <Haben-Betrag></Haben-Betrag>
</Buchungszeile>
<Buchungszeile>
  <Buchungstag>2019-12-06</Buchungstag>
  <Soll-Betrag></Soll-Betrag>
  <Haben-Betrag>155</Haben-Betrag>
</Buchungszeile>
<Buchungszeile>
  <Buchungstag>2019-12-07</Buchungstag>
  <Soll-Betrag>50</Soll-Betrag>
  <Haben-Betrag></Haben-Betrag>
</Buchungszeile>

Проблема 1. С помощью переменной xsl: $betrag я могу просто отобразить все деньги -значения в одном столбце HTML, отрицательные с начальным знаком «-». Но я не нашел способа получить доступ к этой переменной для функции «Текущий итог sum()».

Проблема 2: Я не могу найти способ сгенерировать новый XML -элемент, например, <Betrag> на лету, содержащий все положительные и отрицательные значения для использования для sum(preceding-sibling::Buchungszeile/Betrag) + Betrag)

Проблема 3. Я не могу найти способ получить доступ к значению предыдущей строки, используя position().

Каким будет правильный способ достичь этого результата:

<table>
 <tr> <td>Buchungstag</td> <td>Betrag</td> <td>Running Total</td> </tr>
 <tr> <td> 2019-12-05</td> <td>  -100</td> <td>         -100</td> </tr>
 <tr> <td> 2019-12-06</td> <td>   155</td> <td>           55</td> </tr>
 <tr> <td> 2019-12-07</td> <td>   -50</td> <td>            5</td> </tr>
</table>

Ответы [ 2 ]

2 голосов
/ 06 августа 2020

Я бы предложил совершенно другой подход, который не только обрабатывает пустые узлы, но также избегает дорогостоящего повторного суммирования предыдущих значений братьев и сестер:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/*">
    <table>
        <tr> 
            <th>Buchungstag</th>
            <th>Betrag</th>
            <th>Running Total</th>
        </tr>
            <xsl:call-template name="generate-rows">
                <xsl:with-param name="nodes" select="Buchungszeile"/>
            </xsl:call-template>
    </table>
</xsl:template>

<xsl:template name="generate-rows">
    <xsl:param name="nodes"/>
    <xsl:param name="prev-balance" select="0"/>
    <xsl:if test="count($nodes)">
        <xsl:variable name="node" select="$nodes[1]"/>
        <xsl:variable name="amount" select="concat('0', $node/Haben-Betrag) - concat('0', $node/Soll-Betrag)"/>
        <xsl:variable name="balance" select="$prev-balance + $amount"/>
        <tr> 
            <td>
                <xsl:value-of select="$node/Buchungstag"/>
            </td>
            <td>
                <xsl:value-of select="$amount"/>
            </td>
            <td>
                <xsl:value-of select="$balance"/>
            </td>
        </tr>
        <!-- recursive call -->
        <xsl:call-template name="generate-rows">
            <xsl:with-param name="nodes" select="$nodes[position() > 1]"/>
            <xsl:with-param name="prev-balance" select="$balance"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>
1 голос
/ 06 августа 2020

В XSLT 3 (поддерживаемом Saxon 9.8 или новее или Saxon- JS 2 или Altova XML 2017 R3 и новее) вы можете использовать аккумулятор:

  <xsl:mode on-no-match="shallow-copy" use-accumulators="total"/>
  
  <xsl:accumulator name="total" as="xs:decimal" initial-value="0">
      <xsl:accumulator-rule match="Buchungszeile/Soll-Betrag[. castable as xs:decimal]"
        select="$value - xs:decimal(.)"/>
      <xsl:accumulator-rule match="Buchungszeile/Haben-Betrag[. castable as xs:decimal]"
        select="$value + xs:decimal(.)"/>
  </xsl:accumulator>
  
  <xsl:template match="transaktionen">
      <table class="buchung">
          <thead>
              <tr>
                  <th>Buchungstag</th>
                  <th>Betrag</th>
                  <th>Running Total</th>
              </tr>
          </thead>
          <tbody>
              <xsl:apply-templates/>
          </tbody>
      </table>
  </xsl:template>
  
  <xsl:template match="Buchungszeile">
      <tr>
          <td>{Buchungstag}</td>
          <td>{if (Soll-Betrag castable as xs:decimal) then -xs:decimal(Soll-Betrag) else xs:decimal(Haben-Betrag)}</td>
          <td>{accumulator-after('total')}</td>
      </tr>
  </xsl:template>

https://xsltfiddle.liberty-development.net/6pS2B6P

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