-1

I'm trying to generate the csv file from XML file by xslt transformation. The beginning of xml file:

 <?xml version="1.0" encoding="UTF-8"?>
    <Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.02"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <BkToCstmrDbtCdtNtfctn>
    <GrpHdr>
            <MsgId>UPDD2021-12-20-18.26.01.660000</MsgId>
            <CreDtTm>2021-12-20T18:26:01</CreDtTm>
    </GrpHdr>
    ...
</BkToCstmrDbtCdtNtfctn>
    </Document>

The transformation file:

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:camt.054.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output indent="yes" method="text"/>
<xsl:variable select="';'" name="delimiter"/>
<xsl:variable name="newline">
<xsl:text> 
</xsl:text>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="BkToCstmrDbtCdtNtfctn/Ntfctn/Ntry/NtryDtls/TxDtls">
    <xsl:value-of select="../../../../GrpHdr/MsgId"/>
    <xsl:value-of select="$delimiter"/>
    <xsl:value-of select="../../../../Ntfctn/CreDtTm"/>
    <xsl:value-of select="$delimiter"/>
    <xsl:value-of select="$newline"/>
</xsl:for-each>
</xsl:template>
</Document>
</xsl:stylesheet>

However the csv file is not generated as it supposed to because it looks like this (each record is on new line):

        UPDD2021-12-20-18.26.01.660000
        2021-12-20T18:26:01
    
    
        003409153772021-12-20-18.26.01.9625
        2021-12-20T18:26:01

When I delete tag Document> from both files it looks correctly (with added ';' and each on one line):

UPDD2021-12-20-18.26.01.660000;2021-12-20T18:26:01;

Does somebody know how to update the transformation file to get the csv looking correctly?

Problem resolved. Correct transformation:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camt="urn:iso:std:iso:20022:tech:xsd:camt.054.001.02"
          exclude-result-prefixes="camt">
<xsl:output indent="yes" method="text"/>
<xsl:variable select="';'" name="delimiter"/>
<xsl:variable name="newline">
<xsl:text> 
</xsl:text>
</xsl:variable>
<xsl:template match="/">
<xsl:for-each select="camt:Document/camt:BkToCstmrDbtCdtNtfctn/camt:Ntfctn/camt:Ntry/camt:NtryDtls/camt:TxDtls">
    <xsl:value-of select="../../../../camt:GrpHdr/camt:MsgId"/>
    <xsl:value-of select="$delimiter"/>
    <xsl:value-of select="../../../../camt:Ntfctn/camt:CreDtTm"/>
    <xsl:value-of select="$delimiter"/>
<xsl:value-of select="$newline"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Monika98
  • 1
  • 2
  • Please show minimal but complete samples of XML input and XSLT as well as of output you want and the one you get to allow us to understand and reproduce the problem. Your XSLT snippet with a top level `` that then seems to wrap (although you don't show any closing tags) the XSLT code doesn't seem to make any sense at all. – Martin Honnen Dec 29 '21 at 10:46
  • Please post a [mcve] incl. an example input and the expected output. -- Hint: (1) Remove the `Document` tags from your stylesheet; (2) See here how to handle an XML input that uses a default namespace: https://stackoverflow.com/a/34762628/3016153 – michael.hor257k Dec 29 '21 at 11:57

2 Answers2

0

If the </Document> end tag appears at the end of the stylesheet (which you haven't shown us) then all your XSLT code is within a top-level data element, which is equivalent to commenting it out. The result is that you've executed the "null stylesheet" on the source document, which will copy the text nodes from the source document and ignore everything else.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
0

With an XSLT 2 or 3 processor you want to declare e.g. xpath-default-namespace=""urn:iso:std:iso:20022:tech:xsd:camt.054.001.02" on the xsl:stylesheet element and then write paths within the XSLT code where you can use the local element names from the input documents. Any xsl:template needs to be a top-level child of xsl:stylesheet.

For an XSLT 1 processor you need to bind the namespace URI to a prefix in the XSLT (e.g. xmlns:camt="urn:iso:std:iso:20022:tech:xsd:camt.054.001.02") and use that prefix to qualify any element names in path expressions.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110