Перенумеровать счета-фактуры LineNumber и заменить NaN на 0, используя xslt - PullRequest
1 голос
/ 02 мая 2020

Извините, что снова вас беспокою, но я с трудом отрываюсь от земли с помощью XSLT. Во всех сделанных мною поисках я не вижу ответов на эти вопросы. Интересно, если бы вы узнали, что люди XSLT могут помочь мне, пожалуйста ..

Я получаю счета в XML, в которых есть 3 вопроса, с которыми мне нужно разобраться:

  1. Проблема 1 заключается в том, что мы получаем кредитовые заметки, а некоторые теги LineNumber равны 0 (а если два имеют 0, то наш импорт завершается неудачно, поскольку таблица строк имеет уникальный индекс по счету-фактуре / кредиту и номеру строки (что нормально)).

  2. Проблема 2 заключается в том, что новый поставщик добавляет 10000 и x 10 к номерам строк, которые они добавляют после нашего начального заказа, поэтому, если у нас есть 3 заказанных строки и они добавляют две, номера строк в счете-фактуре равны 1, 2,3 10040 и 10050. Наша (сумасшедшая) получающая таблица имеет максимальное значение 255 для номеров строк.

  3. Проблема 3 заключается в том, что некоторые значения иногда имеют NaN в теге уровня строки InvoicedQuantity и наша таблица имеет десятичный тип.

Меня не интересует сохранение номеров строк, поэтому для решения этих проблем я буду sh:

  1. Изменить значение тегов InvoicedQuantity и другие затронутые теги равны 0, если NaN
  2. Сброс тегов LineNumber от 1 до максимума в физическом порядке

Вот пример файла XML (вырублен, чтобы содержать только вынужденные проблемы)

<?xml version="1.0" encoding="UTF-8"?>
<Invoice>
    <InvoiceHeader>
        <InvoiceReferences>
            <InvoiceReference>ABC123</InvoiceReference>
            <InvoiceDate>2020-03-11</InvoiceDate>
        </InvoiceReferences>
        <CostCentreCode>H020</CostCentreCode>
    </InvoiceHeader>
    <InvoiceDetail>
        <InvoiceLine>
            <LineNumber>0</LineNumber>
            <SuppliersProductCode>A0</SuppliersProductCode>
            <BuyersProductCode>ABC120</BuyersProductCode>
            <ProductDescription>Product Z</ProductDescription>
            <InvoicedQuantity UnitOfMeasure="EA">2</InvoicedQuantity>
            <PackSize>1</PackSize>
            <UnitValueExclVAT>5</UnitValueExclVAT>
            <LineValueExclVAT>10</LineValueExclVAT>
            <VATCode>Z</VATCode>
            <VATRate>0.00</VATRate>
        </InvoiceLine>
        <InvoiceLine>
            <LineNumber>1</LineNumber>
            <SuppliersProductCode>A1</SuppliersProductCode>
            <BuyersProductCode>ABC123</BuyersProductCode>
            <ProductDescription>Product A</ProductDescription>
            <InvoicedQuantity UnitOfMeasure="EA">2</InvoicedQuantity>
            <PackSize>1</PackSize>
            <UnitValueExclVAT>7.45</UnitValueExclVAT>
            <LineValueExclVAT>18.70</LineValueExclVAT>
            <VATCode>Z</VATCode>
            <VATRate>0.00</VATRate>
        </InvoiceLine>
        <InvoiceLine>
            <LineNumber>10020</LineNumber>
            <SuppliersProductCode>B1</SuppliersProductCode>
            <BuyersProductCode>ABC1456</BuyersProductCode>
            <ProductDescription>Product B</ProductDescription>
            <InvoicedQuantity UnitOfMeasure="EA">NaN</InvoicedQuantity>
            <PackSize>1</PackSize>
            <UnitValueExclVAT>7.45</UnitValueExclVAT>
            <LineValueExclVAT>NaN</LineValueExclVAT>
            <VATCode>Z</VATCode>
            <VATRate>0.00</VATRate>
        </InvoiceLine>
    </InvoiceDetail>
    <InvoiceTrailer>
    </InvoiceTrailer>
</Invoice>

Ответы [ 2 ]

2 голосов
/ 02 мая 2020

Используйте эти шаблоны в сочетании с XSLT-1.0 Шаблон идентификации :

  1. Замените значения NaN на 0

    <xsl:template match="InvoiceLine/InvoicedQuantity[text()='NaN']">
        <xsl:copy>
            <xsl:copy-of select="@*" />
            <xsl:value-of select="'0'" />
        </xsl:copy>
    </xsl:template>
    
  2. И перенумеровать все LineNumber, начиная с 1 в порядке документов:

    <xsl:template match="InvoiceLine/LineNumber">
        <xsl:copy>
            <xsl:value-of select="count(../preceding-sibling::InvoiceLine)+1" />
        </xsl:copy>
    </xsl:template>    
    
1 голос
/ 02 мая 2020

Вот измененное преобразование идентичности со специальной обработкой для LineNumber и InvoicedQuantity, надеюсь, это поможет.

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match='InvoiceDetail'>
        <xsl:element name='InvoiceDetail'>
            <xsl:for-each select='InvoiceLine'>
                <xsl:copy>
                    <!-- Create a sequential line # -->
                    <xsl:element name='LineNumber'>
                        <xsl:value-of select='position()'/>
                    </xsl:element>

                    <xsl:apply-templates select="@*|node()"/>

                </xsl:copy>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>

    <!-- Templates to handle our special cases -->
    <xsl:template match='LineNumber'>
        <!-- Nothing, get rid of the existing line #s -->
    </xsl:template>

    <xsl:template match='InvoicedQuantity'>
        <xsl:element name='InvoicedQuantity'>
            <xsl:apply-templates select="@*"/>
            <!-- Convert NaN to 1 -->
            <xsl:if test='(.="NaN")'>1</xsl:if>
            <xsl:if test='not(.="NaN")'><xsl:value-of select='.'/></xsl:if>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>
...