XSLT 2 | Саксон ОН 9.5.1-2 | Начальный выбор шаблона - PullRequest
0 голосов
/ 13 марта 2020

Следующий XSLT выполняет преобразование ввода в вывод без шва на Stylus Studio :

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" exclude-result-prefixes="xs"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="COEP_FilePath"/>

    <xsl:template name="main>
        <xsl:element name="actualUpload" exclude-result-prefixes="xs">
            <xsl:choose>
                <xsl:when test="(not($COEP_FilePath) and not(string($COEP_FilePath)))">
                    <xsl:message terminate="yes">One or more Input Parameter(s) not supplied!</xsl:message>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:variable name="COEPData" select="unparsed-text($COEP_FilePath)"/>
                    <xsl:variable name="Tokenized_COEPData" select="tokenize($COEPData, '\r\n')"/>
                    <xsl:variable name="Period" select="normalize-space(tokenize(tokenize($COEPData, '\r\n')[1], '~')[3])"/>
                    <xsl:variable name="FiscalYear" select="normalize-space(tokenize(tokenize($COEPData, '\r\n')[1], '~')[6])"/>                    
                    <xsl:variable name="Orders" as="element(Orders)*" exclude-result-prefixes="xs">
                        <Orders>
                            <xsl:for-each select="$Tokenized_COEPData">
                                <xsl:variable name="valueInContext" select="tokenize(., '~')"/>
                                <Order>
                                    <!--<period>
                                        <xsl:value-of select="normalize-space($valueInContext[3])"/>
                                    </period>
                                    <finYear>
                                        <xsl:value-of select="normalize-space($valueInContext[6])"/>
                                    </finYear>
                                    <actualRecId>
                                        <xsl:value-of select="normalize-space($valueInContext[2])"/>
                                    </actualRecId>-->
                                    <cur>
                                        <xsl:value-of select="normalize-space($valueInContext[9])"/>
                                    </cur>
                                    <amount>
                                        <xsl:value-of select="if (ends-with(normalize-space($valueInContext[4]), '-')) then concat('-', substring-before(normalize-space($valueInContext[4]), '-')) else normalize-space($valueInContext[4])"/>
                                    </amount>
                                    <internalOrderNum>
                                        <xsl:value-of select="normalize-space($valueInContext[5])"/>
                                    </internalOrderNum>
                                </Order>
                            </xsl:for-each>
                        </Orders>
                    </xsl:variable>
                    <period>
                        <xsl:value-of select="$Period"/>
                    </period>
                    <finYear>
                        <xsl:value-of select="$FiscalYear"/>
                    </finYear>
                    <actuals>
                        <xsl:for-each-group select="$Orders/*" group-by="concat(internalOrderNum, '|', cur)">
                            <actualRec id="{internalOrderNum}">
                                <cur>
                                    <xsl:value-of select="cur"/>
                                </cur>
                                <amount>
                                    <xsl:value-of select="sum(current-group()/xs:decimal(amount))"/>
                                </amount>
                            </actualRec>    
                        </xsl:for-each-group>
                    </actuals>              
                </xsl:otherwise>
            </xsl:choose>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Чтобы это работало, мне пришлось указать начальное значение шаблона для main в разделе Свойства сценария / Процессор Stylus Studio. XSLT будет использоваться в приложении java [iWay Service Manager, который использует библиотеку Saxon HE 9.5.1-2], и я не могу найти метод для указания исходного шаблона. Возможно, существует опция JVM, которую я мог бы использовать, но я смотрю на inte rnet, пока нет показов.

Тем временем, моя попытка обойти проблему, чтобы заменить пользовательское имя шаблона " main "to" xsl: initial-template ", в ответ на замечание об упоминании об этом для работы над другими обсуждениями SO, не оказался успешным. Даже в Stylus Studio, поскольку здесь также используется более старая версия Saxon lib. Я понимаю, что используемая библиотека Saxon HE требует обновления до последней версии обслуживания. Однако это окажет более широкое влияние на приложение java, так как мы обязаны проводить регрессионный тест существующих решений / et c.

Из-за недостатка времени я хотел бы изучить только следующие два варианта:

1) Использование файла конфигурации, в котором, по-видимому, можно указать начальное имя шаблона. Однако мне нужны некоторые советы о том, как включить это в приложении java;

2) Рекомендации по перезаписи XSLT, чтобы он не сталкивался с ошибкой синтаксического анализа в результате использования unparsed -text () function;

Для чего стоит, вот пример ввода:

1000~1234567890~007~            12345.05-~ORDUMMYORD1        ~2019~A~04~EUR  ~          ~0212~
1000~0987654321~007~             12345.05~ORDUMMYORD1        ~2019~S~04~EUR  ~ABCDEFGHIJ~0212~
1000~6789054321~007~                  20-~ORDUMMYORD3        ~2019~A~04~EUR  ~          ~0184~

и соответствующий ему вывод:

<?xml version='1.0' encoding='UTF-8' ?>
<actualUpload>
  <period>007</period>
  <finYear>2019</finYear>
  <actuals>
    <actualRec id="ORDUMMYORD1">
      <cur>EUR</cur>
      <amount>0</amount>
    </actualRec>
    <actualRec id="ORDUMMYORD3">
      <cur>EUR</cur>
      <amount>-20</amount>
    </actualRec>
  </actuals>
</actualUpload>

Пожалуйста, предложите. Thx.

РЕДАКТИРОВАТЬ 1: 13:39 CET

Я изменил XSLT на следующие, которые решают проблему вокруг:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" exclude-result-prefixes="xs"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="COEP_FilePath"/>

    <xsl:template match="/">
        <xsl:element name="actualUpload" exclude-result-prefixes="xs">
            <xsl:choose>
                <xsl:when test="(not($COEP_FilePath) and not(string($COEP_FilePath)))">
                    <xsl:message terminate="yes">One or more Input Parameter(s) not supplied!</xsl:message>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:variable name="COEPData">
                        <root>
                            <xsl:value-of select="unparsed-text($COEP_FilePath)"/>
                        </root>
                    </xsl:variable>
                    <xsl:variable name="Tokenized_COEPData" select="tokenize($COEPData/root, '\r\n')"/>
                    <xsl:variable name="Period" select="normalize-space(tokenize(tokenize($COEPData/root, '\r\n')[1], '~')[3])"/>
                    <xsl:variable name="FiscalYear" select="normalize-space(tokenize(tokenize($COEPData/root, '\r\n')[1], '~')[6])"/>
                    <xsl:variable name="Orders" as="element(Orders)*" exclude-result-prefixes="xs">
                        <Orders>
                            <xsl:for-each select="$Tokenized_COEPData">
                                <xsl:variable name="valueInContext" select="tokenize(., '~')"/>
                                <Order>
                                    <!--<period>
                                        <xsl:value-of select="normalize-space($valueInContext[3])"/>
                                    </period>
                                    <finYear>
                                        <xsl:value-of select="normalize-space($valueInContext[6])"/>
                                    </finYear>
                                    <actualRecId>
                                        <xsl:value-of select="normalize-space($valueInContext[2])"/>
                                    </actualRecId>-->
                                    <cur>
                                        <xsl:value-of select="normalize-space($valueInContext[9])"/>
                                    </cur>
                                    <amount>
                                        <xsl:value-of select="if (ends-with(normalize-space($valueInContext[4]), '-')) then concat('-', substring-before(normalize-space($valueInContext[4]), '-')) else normalize-space($valueInContext[4])"/>
                                    </amount>
                                    <internalOrderNum>
                                        <xsl:value-of select="normalize-space($valueInContext[5])"/>
                                    </internalOrderNum>
                                </Order>
                            </xsl:for-each>
                        </Orders>
                    </xsl:variable>
                    <period>
                        <xsl:value-of select="$Period"/>
                    </period>
                    <finYear>
                        <xsl:value-of select="$FiscalYear"/>
                    </finYear>
                    <actuals>
                        <xsl:for-each-group select="$Orders/*" group-by="concat(internalOrderNum, '|', cur)">
                            <actualRec id="{internalOrderNum}">
                                <cur>
                                    <xsl:value-of select="cur"/>
                                </cur>
                                <amount>
                                    <xsl:value-of select="sum(current-group()/xs:decimal(amount))"/>
                                </amount>
                            </actualRec>
                        </xsl:for-each-group>
                    </actuals>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Хотя было бы неплохо, если бы ниже было прокомментировано. Спасибо.

1) Использование файла конфигурации, в котором, по-видимому, можно указать начальное имя шаблона. Хотя мне нужно несколько советов о том, как включить это в приложении java;

1 Ответ

0 голосов
/ 13 марта 2020

Добавление функционала XSLT для справки. Переменная COEPData теперь имеет тег XML, окружающий unparsed-text (), что позволяет процессору продолжить работу.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" exclude-result-prefixes="xs"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="COEP_FilePath"/>

    <xsl:template match="/">
        <xsl:element name="actualUpload" exclude-result-prefixes="xs">
            <xsl:choose>
                <xsl:when test="(not($COEP_FilePath) and not(string($COEP_FilePath)))">
                    <xsl:message terminate="yes">One or more Input Parameter(s) not supplied!</xsl:message>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:variable name="COEPData">
                        <root>
                            <xsl:value-of select="unparsed-text($COEP_FilePath)"/>
                        </root>
                    </xsl:variable>
                    <xsl:variable name="Tokenized_COEPData" select="tokenize($COEPData/root, '\r\n')"/>
                    <xsl:variable name="Period" select="normalize-space(tokenize(tokenize($COEPData/root, '\r\n')[1], '~')[3])"/>
                    <xsl:variable name="FiscalYear" select="normalize-space(tokenize(tokenize($COEPData/root, '\r\n')[1], '~')[6])"/>
                    <xsl:variable name="Orders" as="element(Orders)*" exclude-result-prefixes="xs">
                        <Orders>
                            <xsl:for-each select="$Tokenized_COEPData">
                                <xsl:variable name="valueInContext" select="tokenize(., '~')"/>
                                <Order>
                                    <!--<period>
                                        <xsl:value-of select="normalize-space($valueInContext[3])"/>
                                    </period>
                                    <finYear>
                                        <xsl:value-of select="normalize-space($valueInContext[6])"/>
                                    </finYear>
                                    <actualRecId>
                                        <xsl:value-of select="normalize-space($valueInContext[2])"/>
                                    </actualRecId>-->
                                    <cur>
                                        <xsl:value-of select="normalize-space($valueInContext[9])"/>
                                    </cur>
                                    <amount>
                                        <xsl:value-of select="if (ends-with(normalize-space($valueInContext[4]), '-')) then concat('-', substring-before(normalize-space($valueInContext[4]), '-')) else normalize-space($valueInContext[4])"/>
                                    </amount>
                                    <internalOrderNum>
                                        <xsl:value-of select="normalize-space($valueInContext[5])"/>
                                    </internalOrderNum>
                                </Order>
                            </xsl:for-each>
                        </Orders>
                    </xsl:variable>
                    <period>
                        <xsl:value-of select="$Period"/>
                    </period>
                    <finYear>
                        <xsl:value-of select="$FiscalYear"/>
                    </finYear>
                    <actuals>
                        <xsl:for-each-group select="$Orders/*" group-by="concat(internalOrderNum, '|', cur)">
                            <actualRec id="{internalOrderNum}">
                                <cur>
                                    <xsl:value-of select="cur"/>
                                </cur>
                                <amount>
                                    <xsl:value-of select="sum(current-group()/xs:decimal(amount))"/>
                                </amount>
                            </actualRec>
                        </xsl:for-each-group>
                    </actuals>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>
...