Как удалить пустые строки из XML в CSV-вывод в XSLT3.0 - PullRequest
0 голосов
/ 01 ноября 2019

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

Я попытался установить глобальную переменную, но ни один из них не работал с двумя используемыми шаблонами.

    <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
    <xsl:strip-space elements="*"/>
    <xsl:variable name="delimiter" select="','"/>
    <xsl:param name="xslt.transform.params"></xsl:param>
    <xsl:variable name="countryCode">
        <xsl:value-of select="$xslt.transform.params"/>
    </xsl:variable>
    <csv:columns>
        <column>ORIG</column>
        <column>CUST</column>
        <column>PARTY</column>
        <column>ACCOUNT1</column>
        <column>ACCOUNT2</column>
        <column>CURRENCY</column>
        <column>SUM1</column>
        <column>SUM2</column>
        <column>SUM3</column>
        <column>SUM4</column>
        <column>SUM5</column>
        <column>SUM6</column>
        <column>SUM7</column>
        <column>SUM8</column>
        <column>SUM9</column>
        <column>SUM10</column>
        <column>SUM11</column>
        <column>SUM12</column>
    </csv:columns>
    <xsl:template match="/">
        <xsl:for-each select="document('')/*/csv:columns/*">
            <xsl:value-of select="."/>
            <xsl:if test="position() != last()">
                <xsl:value-of select="$delimiter"/>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xa;</xsl:text>
        <xsl:apply-templates select="*"/>
    </xsl:template>
    <xsl:template match="/DATA/G">
        <xsl:variable name="result" select="."/>
        <xsl:variable name="orgsysref" select="ORIG"/>
        <xsl:for-each select="document('')/*/csv:columns/*">
            <xsl:variable name="vCountry" select="fn:substring($orgsysref,1,2)"/>
            <xsl:if test="$vCountry = fn:substring-before($countryCode,'|') or $vCountry = fn:substring-after($countryCode, '|') or $vCountry = $countryCode">
                <xsl:variable name="column" select="."/>
                <xsl:variable name="value" select="$result/*[name() = $column]"/>
                <xsl:value-of select="$value"/>
                <xsl:if test="position() != last()">
                    <xsl:value-of select="$delimiter"/>
                </xsl:if>
            </xsl:if>
        </xsl:for-each>
        <xsl:text>&#xa;</xsl:text>
    </xsl:template>
</xsl:stylesheet>

входное сообщение:

<DATA>
    <G>
        <ORIG>test107015196</ORIG>
        <CUST>30AB00000197776</CUST>
        <PARTY>customer</PARTY>
        <ACCOUNT1>0432007015196</ACCOUNT1>
        <ACCOUNT2>Customer</ACCOUNT2>
        <CURRENCY>EUR</CURRENCY>
        <SUM1>440.26</SUM1>
        <SUM2>3</SUM2>
        <SUM3>0</SUM3>
        <SUM4>0</SUM4>
        <SUM5>16.66</SUM5>
        <SUM6>1</SUM6>
        <SUM7>423.6</SUM7>
        <SUM8>2</SUM8>
        <SUM9>0</SUM9>
        <SUM10>0</SUM10>
        <SUM11>0</SUM11>
        <SUM12>0</SUM12>
    </G>
    <G>
        <ORIG>test106438731</ORIG>
        <CUST>3000KJ3324638</CUST>
        <PARTY>Distrißüter</PARTY>
        <ACCOUNT1>04910438731</ACCOUNT1>
        <ACCOUNT2>Distrißüter</ACCOUNT2>
        <CURRENCY>EUR</CURRENCY>
        <SUM1>312.18</SUM1>
        <SUM2>1</SUM2>
        <SUM3>0</SUM3>
        <SUM4>0</SUM4>
        <SUM5>312.18</SUM5>
        <SUM6>1</SUM6>
        <SUM7>0</SUM7>
        <SUM8>0</SUM8>
        <SUM9>0</SUM9>
        <SUM10>0</SUM10>
        <SUM11>0</SUM11>
        <SUM12>0</SUM12>
    </G>
    <G>
        <ORIG>test203084024</ORIG>
        <CUST>30XY0013478518</CUST>
        <PARTY>Test UAT DE</PARTY>
        <ACCOUNT1>0492003f084024</ACCOUNT1>
        <ACCOUNT2>Testing UAT DE</ACCOUNT2>
        <CURRENCY>EUR</CURRENCY>
        <SUM1>2745.79</SUM1>
        <SUM2>12</SUM2>
        <SUM3>0</SUM3>
        <SUM4>0</SUM4>
        <SUM5>2751.68</SUM5>
        <SUM6>11</SUM6>
        <SUM7>-5.89</SUM7>
        <SUM8>1</SUM8>
        <SUM9>0</SUM9>
        <SUM10>0</SUM10>
        <SUM11>0</SUM11>
        <SUM12>0</SUM12>
    </G>
</DATA>

Фактический результат:

ORIG,CUST,PARTY,ACCOUNT1,ACCOUNT2,CURRENCY,SUM1,SUM2,SUM3,SUM4,SUM5,SUM6,SUM7,SUM8,SUM9,SUM10,SUM11,SUM12

Ожидаемый результат: нет вывода с какими-либо заголовками.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 01 ноября 2019

Вы выполняете работу внутри цикла для каждого столбца, которая может быть выполнена вне его, и исправление этой проблемы решит проблему:

<xsl:template match="/DATA/G">
        <xsl:variable name="result" select="."/>
        <xsl:variable name="orgsysref" select="ORIG"/>
        <xsl:variable name="vCountry" select="fn:substring($orgsysref,1,2)"/>
        <xsl:if test="$vCountry = fn:substring-before($countryCode,'|') or $vCountry = fn:substring-after($countryCode, '|') or $vCountry = $countryCode">
            <xsl:for-each select="document('')/*/csv:columns/*">
                <xsl:variable name="column" select="."/>
                <xsl:variable name="value" select="$result/*[name() = $column]"/>
                <xsl:value-of select="$value"/>
                <xsl:if test="position() != last()">
                    <xsl:value-of select="$delimiter"/>
                </xsl:if>
             </xsl:for-each>
          <xsl:text>&#xa;</xsl:text>
       </xsl:if>
    </xsl:template>

Обратите внимание, как символ новой строки теперь выводится в условном выражении.

В качестве бонуса пара комментариев к вашему коду:

(a) Более эффективно выводить разделитель перед каждым элементом, отличным от первого, а не после каждого элемента, отличного от последнего,Это связано с тем, что он не включает прогнозирование (оценка last()), поэтому не нарушает конвейерную оценку. Конечно, некоторые процессоры все равно оптимизируют это для вас.

(b) использование документа ('') для доступа к таблице стилей во время выполнения - довольно ужасное похмелье от XSLT 1.0. Гораздо лучше поместить данные в глобальную переменную. С документом (''), (i) исходная таблица стилей должна быть доступна во время выполнения, а не только во время компиляции, и (ii) вы должны прочитать ее дважды, потому что правила для удаления пробелов в исходных документах отличаются отте, в таблицах стилей.

0 голосов
/ 01 ноября 2019

Переместите <xsl:text>&#xa;</xsl:text> в xsl:if и измените вложенность, оберните <xsl:for-each select="document('')/*/csv:columns/*"> в xsl:if, мне кажется, что test="$vCountry = fn:substring-before($countryCode,'|') or $vCountry = fn:substring-after($countryCode, '|') or $vCountry = $countryCode" никак не зависит от значения этогоfor-each.

В конце весь код выглядит как XSLT 1 вместо использования XSLT 2 или 3 функций (таких как переменные типа xs:string*, сравнение с = просто в шаблоне или apply-templates, xsl:value-of separator для вывода значений через запятую).

...