Приведенный ниже код XSLT позволяет конвертировать XML в CSV с заключенными в кавычки, но дочерний узел (Подробности) отображается в той же строке.
Обновление: Как уже упоминалось на форуме, я обновил вопрос с ожидаемым результатом.
XML-ввод
<?xml version = "1.0" encoding = "UTF-8"?>
<Root>
<Records>
<TrRecords>
<RecordID>0123</RecordID>
<SequnceNumber>00001</SequnceNumber>
<TNumber>00001</TNumber>
<System>01</System>
<Amount>4956.00</Amount>
<Reference>T</Reference>
<Account>89768</Account>
<Name>bdi</Name>
<Other2/>
<Other3/>
<Details>
<RecordID>1234</RecordID>
<SequnceNumber>00001</SequnceNumber>
<TNumber>00001</TNumber>
<Number>TI</Number>
<InvoiceDate>2024-05-05</InvoiceDate>
<InvoiceDescription/>
<InvoiceAmount>10.00</InvoiceAmount>
</Details>
<Details>
<RecordID>1234</RecordID>
<SequnceNumber>00002</SequnceNumber>
<TNumber>00001</TNumber>
<Number>TI3</Number>
<InvoiceDate>2024-05-05</InvoiceDate>
<InvoiceDescription/>
<InvoiceAmount>10.00</InvoiceAmount>
</Details>
</TrRecords>
<TrRecords>
<RecordID>0123</RecordID>
<SequnceNumber>00001</SequnceNumber>
<TNumber>00002</TNumber>
<System>01</System>
<Amount>523.00</Amount>
<Reference>TI</Reference>
<Account>18907</Account>
<Name>elci</Name>
<Other2/>
<Other3/>
<Details>
<RecordID>1234</RecordID>
<SequnceNumber>00001</SequnceNumber>
<TNumber>00001</TNumber>
<Number>TIR</Number>
<InvoiceDate>2024-08-17</InvoiceDate>
<InvoiceDescription/>
<InvoiceAmount>5245.00</InvoiceAmount>
</Details>
</TrRecords>
<TrRecords>
<RecordID>0123</RecordID>
<Number>00001</Number>
<TNumber>00003</TNumber>
<System>01</System>
<Amount>1180.00</Amount>
<Reference>EMI</Reference>
<AccountNo>0936201002941</AccountNo>
<Other2/>
<Other3/>
<Details>
<RecordID>1234</RecordID>
<SequnceNumber>00001</SequnceNumber>
<TNumber>00001</TNumber>
<Number>Tac</Number>
<InvoiceDate>2024-08-17</InvoiceDate>
<InvoiceDescription/>
<InvoiceAmount>1180.00</InvoiceAmount>
</Details>
</TrRecords>
</Records>
</Root>
XSLT-код
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "text" encoding = "utf-8" />
<xsl:param name = "delim" select = "','" />
<xsl:param name = "quote" select = "'"'" />
<xsl:param name = "break" select = "'
'" />
<xsl:template match = "/Root">
<xsl:apply-templates select = "Records/TrRecords" />
</xsl:template>
<xsl:template match = "TrRecords">
<xsl:apply-templates />
<xsl:if test = "following-sibling::*">
<xsl:value-of select = "$break" />
</xsl:if>
<xsl:for-each select = "Details">
<xsl:if test = "following-sibling::*">
<xsl:value-of select = "$break" />
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match = "*">
<!-- remove normalize-space() -->
<xsl:value-of select = "concat($quote, normalize-space(), $quote)" />
<xsl:if test = "following-sibling::*">
<xsl:value-of select = "$delim" />
</xsl:if>
</xsl:template>
<xsl:template match = "text()" />
</xsl:stylesheet>
Ожидаемый результат
"0123","00001","00001","01","4956.00","T","89768","bdi","",""
"1234","00001","00001","TI","2024-05-05","","10.00"
"1234","00002","00001","TI3","2024-05-05","","10.00"
"0123","00001","00002","01","523.00","TI","18907","elci","",""
"1234","00001","00001","TIR","2024-08-17","","5245.00"
"0123","00001","00003","01","1180.00","EMI","0936201002941","",""
"1234","00001","00001","Tac","2024-08-17","","1180.00"
В каждой строке, начиная с 1234, значения должны идти с новой строки и заключаться в кавычки. не могли бы вы помочь мне с этим?
С уважением, Джанардхан
@michael.hor257k Я обновил вопрос с ожидаемым результатом.
(измененный)
Попробуйте что-то вроде:
<xsl:stylesheet version = "2.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "text" encoding = "utf-8" />
<xsl:strip-space elements = "*"/>
<xsl:param name = "delim" select = "','" />
<xsl:param name = "quote" select = "'"'" />
<xsl:param name = "break" select = "'
'" />
<xsl:template match = "/Root">
<xsl:apply-templates select = "Records/TrRecords" />
</xsl:template>
<xsl:template match = "TrRecords">
<xsl:apply-templates select = "* except Details"/>
<xsl:apply-templates select = "Details"/>
<xsl:if test = "position()!=last()">
<xsl:value-of select = "$break" />
</xsl:if>
</xsl:template>
<xsl:template match = "Details">
<xsl:value-of select = "$break" />
<xsl:apply-templates/>
</xsl:template>
<xsl:template match = "*">
<xsl:value-of select = "concat($quote, normalize-space(), $quote)" />
<xsl:if test = "position()!=last()">
<xsl:value-of select = "$delim" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Демо здесь.
Обратите внимание, что это предполагает, что ни одно из значений, переданных на выход, не содержит кавычек.
Я пробовал использовать приведенный выше код, но в TrRecrods, если несколько сегментов сведений находятся в XML, то они отображаются в одной строке. Ниже приведен пример. "1234","00001","00001","TI","2024-05-05","","10.00","1234","00003","00001","TI3" ,"2024-05-05","","10.00"
В исходном вопросе не было нескольких деталей. Я изменил свой ответ, но...
Я попробовал обновленный код, и теперь записи сведений заполняются в одной строке TrRecords. Подробные записи должны быть в новой строке. "0123","00001","00001","01","4956.00","T","89768","bdi","","","1234 00001 00001 TI 2024-05-05 10.00","1234 00002 00001 TI3 05.05.2024 10.00" "0123","00001","00002","01","523.00","TI","18907","elci","", "","1234 00001 00001 TIR 2024-08-17 5245.00" "0123","00001","00003","01","1180.00","EMI","0936201002941","", "","1234 00001 00001 Tac 17.08.2024 1180.00"
Это не тот результат, который я получаю (см. ссылку в моем ответе).
Проблема с моим приложением. Кажется, теперь он работает нормально. Большое спасибо за вашу помощь!
Основная проблема заключается в том, что в шаблоне, который соответствует TrRecords
, вы вызываете apply-templates
для обработки всех дочерних элементов TrRecords
, включая элементы Details
, но затем позже вы снова явно перебираете эти Details
элементы.
Вот таблица стилей с 4 шаблонами:
TrRecords
,TrRecords
и применяет шаблоны к их дочерним элементамDetails
и применяет шаблоны к своим дочерним элементам (обратите внимание: это гарантирует, что элемент Details
, найденный внутри элемента TrRecords
, обрабатывается как строка вывода, содержащая элементы, которые являются столбцами, а не обрабатывается как сам столбец)Обратите внимание: шаблон TrRecords
добавляет разрыв строки после обработки дочерних элементов, а шаблон Details
добавляет разрыв строки перед обработкой дочерних элементов.
Также обратите внимание, что строка $delim
вставляется после рендеринга значения столбца, только если есть следующие одноуровневые элементы, кроме Details
элементов.
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "text" encoding = "utf-8" />
<xsl:param name = "delim" select = "','" />
<xsl:param name = "quote" select = "'"'" />
<xsl:param name = "break" select = "'
'" />
<xsl:template match = "/">
<xsl:apply-templates select = "Root/Records/TrRecords" />
</xsl:template>
<xsl:template match = "TrRecords">
<xsl:apply-templates select = "*"/>
<xsl:value-of select = "$break" />
</xsl:template>
<xsl:template match = "Details">
<xsl:value-of select = "$break" />
<xsl:apply-templates select = "*"/>
</xsl:template>
<xsl:template match = "*">
<xsl:value-of select = "concat($quote, ., $quote)" />
<xsl:if test = "following-sibling::*[not(self::Details)]">
<xsl:value-of select = "$delim" />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Однако лично я, если бы у меня был доступный интерпретатор XSLT 2, я был бы склонен написать это по-другому, используя только один шаблон и более сложное выражение XPath:
<xsl:stylesheet version = "2.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
<xsl:output method = "text" encoding = "utf-8" />
<xsl:param name = "delim" select = "','" />
<xsl:param name = "quote" select = "'"'" />
<xsl:param name = "break" select = "'
'" />
<xsl:template match = "/">
<xsl:value-of separator = "{$break}" select = "
for $row in
(Root/Records/TrRecords | Root/Records/TrRecords/Details)
return
string-join(
for $col in $row/*[not(self::Details)] return concat($quote, $col, $quote),
$delim
)
"/>
</xsl:template>
</xsl:stylesheet>
Пожалуйста, отредактируйте свой вопрос и покажите точный результат, который вы хотите получить.