Изменение номеров строк в преобразовании XSLT 2.0 - PullRequest
0 голосов
/ 07 марта 2019

У меня возникли проблемы с решением клиентского запроса на их преобразование XML. Они запрашивают, чтобы при получении повторяющихся строк счета-фактуры они хотели автоматически изменить значение повторения для следующего значения в последовательности номеров строк счета-фактуры, см. Входные и ожидаемые выходные данные ниже.

Ввод:

<?xml version="1.0" encoding="UTF-8"?>
    <DatiBeniServizi>
        <DettaglioLinee>
            <NumeroLinea>1</NumeroLinea>
        </DettaglioLinee>
        <DettaglioLinee>
            <NumeroLinea>1</NumeroLinea>
        </DettaglioLinee>
        <DettaglioLinee>
            <NumeroLinea>2</NumeroLinea>
        </DettaglioLinee>
        <DettaglioLinee>
            <NumeroLinea>3</NumeroLinea>
        </DettaglioLinee>
    </DatiBeniServizi>

Ожидаемый результат:

<Invoice>
        <InvoiceDetail>
            <InvoiceLineNumber>1</InvoiceLineNumber>
        </InvoiceDetail>
        <InvoiceDetail>
            <InvoiceLineNumber>4</InvoiceLineNumber>
        </InvoiceDetail>
        <InvoiceDetail>
            <InvoiceLineNumber>2</InvoiceLineNumber>
        </InvoiceDetail>
        <InvoiceDetail>
            <InvoiceLineNumber>3</InvoiceLineNumber>
        </InvoiceDetail>
</Invoice>

Я пытался группировать, но я не получаю результат, как они просят, это звучит легко, но я потратил весь день, пытаясь решить напрасно.

Любая помощь приветствуется, спасибо за ваше время, ребята!

Ответы [ 2 ]

2 голосов
/ 08 марта 2019

Предполагая, что каждый дубликат увеличивается на 1 каждый раз (так что первый дубликат равен 4, а затем следующие 5), одним из способов может быть использование рекурсивного шаблона, который обрабатывает каждый элемент по очереди и увеличивает параметркогда он находит дубликат).

Чтобы найти дубликаты, я вернулся к использованию мюнхенской группировки, которая обычно используется в XSLT 1.0

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes" />

  <xsl:key name="invoices" match="DettaglioLinee" use="NumeroLinea" />

  <xsl:variable name="max" select="max(/DatiBeniServizi/DettaglioLinee/NumeroLinea)" />

  <xsl:template match="DatiBeniServizi">
    <Invoice>
      <xsl:apply-templates select="DettaglioLinee[1]" />
    </Invoice>
  </xsl:template>

  <xsl:template match="DettaglioLinee">
    <xsl:param name="incr" select="1" />

    <xsl:variable name="isDistinct" select="generate-id() = generate-id(key('invoices', NumeroLinea)[1])" />
    <InvoiceDetail>
      <InvoiceLineNumber>
        <xsl:value-of select="if ($isDistinct) then NumeroLinea else $max + $incr" />
      </InvoiceLineNumber>
    </InvoiceDetail>
    <xsl:apply-templates select="following-sibling::*[1]">
      <xsl:with-param name="incr" select="if ($isDistinct) then $incr else $incr + 1" />
    </xsl:apply-templates>
  </xsl:template>
</xsl:stylesheet>

Если дубликаты всегда были последовательными(т.е. у вас не будет, например, 1, 2, 1), вы удалите использование ключа и определите переменную isDistinct следующим образом:

<xsl:variable name="isDistinct" select="not(NumeroLinea = preceding-sibling::*[1]/NumeroLinea)" />

РЕДАКТИРОВАТЬ: Если вы не беспокоитесь о последовательных числах (например, у вас может быть 1, 5, 2, 3), то вы просто добавляете позицию дубликатов к максимальному значению, что позволит избежать дубликатов

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes" />

  <xsl:key name="invoices" match="DettaglioLinee" use="NumeroLinea" />

  <xsl:variable name="max" select="max(/DatiBeniServizi/DettaglioLinee/NumeroLinea)" />

  <xsl:template match="DatiBeniServizi">
    <Invoice>
      <xsl:apply-templates select="DettaglioLinee" />
    </Invoice>
  </xsl:template>

  <xsl:template match="DettaglioLinee">
    <xsl:variable name="isDistinct" select="generate-id() = generate-id(key('invoices', NumeroLinea)[1])" />
    <InvoiceDetail>
      <InvoiceLineNumber>
        <xsl:value-of select="if ($isDistinct) then NumeroLinea else $max + position()" />
      </InvoiceLineNumber>
    </InvoiceDetail>
  </xsl:template>
</xsl:stylesheet>
1 голос
/ 08 марта 2019

Это смешивает проблему группировки с проблемой нумерации.

Эта таблица стилей XSLT 1.0

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kNumeroLineaByValue" match="NumeroLinea" use="." />
    <xsl:variable name="vNumeroLineaDistinct"
        select="//NumeroLinea[generate-id()=generate-id(key('kNumeroLineaByValue',.))]" />
    <xsl:variable name="vNumeroLineaDistinctCount"
        select="count($vNumeroLineaDistinct)" />
    <xsl:variable name="vNumeroLineaLastValue">
        <xsl:for-each select="$vNumeroLineaDistinct">
            <xsl:sort data-type="number" order="descending" />
            <xsl:if test="position()=1">
                <xsl:value-of select="." />
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="NumeroLinea/text()">
        <xsl:choose>
            <xsl:when
                test="count(..|$vNumeroLineaDistinct)!=$vNumeroLineaDistinctCount">
                <xsl:variable name="vPosition">
                    <xsl:number level="any"
                        count="NumeroLinea[.=preceding::NumeroLinea]" />
                </xsl:variable>
                <xsl:value-of
                    select="$vPosition + $vNumeroLineaLastValue" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

И этот вход

<DatiBeniServizi>
    <DettaglioLinee>
        <NumeroLinea>1</NumeroLinea>
    </DettaglioLinee>
    <DettaglioLinee>
        <NumeroLinea>1</NumeroLinea>
    </DettaglioLinee>
    <DettaglioLinee>
        <NumeroLinea>2</NumeroLinea>
    </DettaglioLinee>
    <DettaglioLinee>
        <NumeroLinea>3</NumeroLinea>
    </DettaglioLinee>
    <DettaglioLinee>
        <NumeroLinea>3</NumeroLinea>
    </DettaglioLinee>
    <DettaglioLinee>
        <NumeroLinea>5</NumeroLinea>
    </DettaglioLinee>
</DatiBeniServizi>

Результат:

<DatiBeniServizi>
      <DettaglioLinee>
            <NumeroLinea>1</NumeroLinea>
      </DettaglioLinee>
      <DettaglioLinee>
            <NumeroLinea>6</NumeroLinea>
      </DettaglioLinee>
      <DettaglioLinee>
            <NumeroLinea>2</NumeroLinea>
      </DettaglioLinee>
      <DettaglioLinee>
            <NumeroLinea>3</NumeroLinea>
      </DettaglioLinee>
      <DettaglioLinee>
            <NumeroLinea>7</NumeroLinea>
      </DettaglioLinee>
      <DettaglioLinee>
            <NumeroLinea>5</NumeroLinea>
      </DettaglioLinee>
</DatiBeniServizi>

Примечание: Группировка для дедупликации, а затем нумерация от начального значения (максимальное значение из всех различных значений)

...