Следующий 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;