DEV Community

Rohith_Veerapalli
Rohith_Veerapalli

Posted on

Convert MT940 to xml in x++

/// <summary>
/// Process class to convert MT940 to XML
/// </summary>
class ProcessMT940BankFiles
{
    /// <summary>
    /// Method to get the request and return response based on process
    /// </summary>
    /// <param name = "_xmlContent">_xmlContent</param>
    /// <returns>xmlOutput</returns>
    public static str getIncomingFileContent(Notes _xmlContent)
    {
        MT940Parameters    mt940Params;

        select firstonly * from mt940Params;


        str xmlOutput = ProcessMT940BankFiles::transformFile(_xmlContent, mt940Params.ESIncomingXSLTFormat);
        xmlOutput = ProcessMT940BankFiles::transformFile(xmlOutput, mt940Params.ESXML2Reconciliation);
        xmlOutput = ProcessMT940BankFiles::transformFile(xmlOutput, mt940Params.ESRecon2Composite);

        return xmlOutput;

    }

    ///// <summary>
    ///// Method to process the MT940 files and translate them accordingly
    ///// </summary>
    ///// <param name = "_inputFileReader">_inputFileReader</param>
    ///// <param name = "_xslReader">_xslReader</param>
    ///// <returns>fileContent</returns>
    static public str transformFile(Notes _inputFileReader, Notes _xslReader)
    {

        System.Xml.XmlUrlResolver               resolver;
        System.Xml.Xsl.XsltSettings             managedSettings;
        System.Xml.Xsl.XslCompiledTransform     managedTransform;

        managedSettings = new System.Xml.Xsl.XsltSettings(true, true);
        resolver = new System.Xml.XmlUrlResolver();
        str fileContent;
        managedTransform = new System.Xml.Xsl.XslCompiledTransform();
        System.Xml.XmlReaderSettings settings = new System.Xml.XmlReaderSettings();
        settings.IgnoreWhitespace = true;
        settings.IgnoreComments = true;
        System.IO.Stream st = new System.IO.MemoryStream(System.Text.Encoding::UTF8.GetBytes(_xslReader));

        // Initialize reader for the xslt
        using(System.IO.StringReader xsltStringReader = new System.IO.StringReader(_xslReader))
        {
            using(System.Xml.XmlReader xsltXmlReader = System.Xml.XmlReader::Create(st,settings))
            {
                // Load xslt
                managedTransform.Load(xsltXmlReader, managedSettings, resolver);
                using(System.IO.StringReader xmlreader = new System.IO.StringReader(_inputFileReader))
                {
                    using(System.Xml.XmlReader inputFileXmlReader = System.Xml.XmlReader::Create(xmlreader))
                    {
                        using (var sw = new System.IO.StringWriter())
                        {
                            using (var xwo = System.Xml.XmlWriter::Create(sw, managedTransform.OutputSettings))
                            {
                                // Transform
                                managedTransform.Transform(inputFileXmlReader, xwo);
                                xwo.Flush();
                                fileContent = sw.ToString();
                                fileContent = strReplace(fileContent,"encoding=\"utf-16\"", '');
                            }
                        }
                    }
                }
            }
        }
        return fileContent;
    }

}
Enter fullscreen mode Exit fullscreen mode

here is the mt940 parameters table data

Field - ESINCOMINGXSLTFORMAT

Value-

<!-- This stylesheet converts the root-tagged MT940 txt file into a flat XML file where each txt record line is converted to its corresponding XML record structure. That XML is then processed by another stylesheet to map to the AX Bank Statement Data Model (BankStmtISO* set of tables). --> <!-- This is the entry point to the transform --> <!-- Select all the text you need to PreProcess and send it to the PreProcessor The PreProcessor returns the value in 'txtToProcess' --> /xsl:call-template /xsl:variable <!-- Call the main template giving it the 'txtToProcess' as a parameter --> /xsl:call-template /xsl:template <!-- This template is similar to the 'main' function in X++. It partitions the file into records and gives the record to the 'rowToFields' template which further partitions it into the corresponding fields. Parameters: 1) rownum - to keep track of the rows parsed so far if required as part of some extension 2) txt - the text that would be handled by this template --> /xsl:variable /xsl:call-template /xsl:if /xsl:template <!-- This template partitions each record into the corresponding fields based on the record type. fields. It also keeps track of the structure of the bank statement by attaching the same 'accountGroup' attribute to all accounts in that accountGroup and the same 'transactionGroup' attribute to all transactions in the same Account. Parameters: 1) txt - the text that would be handled by this template 2) rem - to keep track of the text remaining after the current record 3) accountGroup - the current account group being traversed to poplate the 'accountGroup' attribute 4) transactionGroup - the current transaction group being traversed to poplate the 'transactionGroup' atribute --> /xsl:variable xsl:choose <!-- Record Type '20' indicates Header Reference --> /xsl:call-template /xsl:when <!-- Record Type '25' indicates Header Account Identification --> /xsl:value-of /xsl:attribute /xsl:call-template /xsl:when <!-- Record Type '28C' indicates Statement Identification --> /xsl:value-of /xsl:attribute /xsl:value-of /xsl:attribute /xsl:call-template /xsl:when <!-- Record Type contains '60' indicates Statement Opening --> /xsl:value-of /xsl:attribute /xsl:value-of /xsl:attribute /xsl:call-template /xsl:when <!-- Record Type contains '62' indicates Statement Closing --> /xsl:value-of /xsl:attribute /xsl:value-of /xsl:attribute /xsl:call-template /xsl:when <!-- Record Type '61' indicates Transaction --> /xsl:value-of /xsl:attribute /xsl:value-of /xsl:attribute /xsl:call-template /xsl:when /xsl:choose xsl:choose <!-- call rowToFields recursively for the next record --> /xsl:call-template /xsl:if /xsl:when <!-- call rowToFields recursively for the next record --> /xsl:call-template /xsl:if /xsl:when xsl:otherwise <!-- call rowToFields recursively for the next record --> /xsl:call-template /xsl:if /xsl:otherwise /xsl:choose /xsl:template /xsl:template xsl:choose /xsl:variable /xsl:variable /xsl:variable /xsl:when /xsl:when xsl:otherwise /xsl:otherwise /xsl:choose /xsl:template /xsl:template /xsl:call-template /xsl:template xsl:choose /xsl:when xsl:otherwise /xsl:otherwise /xsl:choose /xsl:variable /xsl:variable /xsl:variable /xsl:variable /xsl:variable /xsl:variable /xsl:call-template /xsl:variable /xsl:variable /xsl:variable /xsl:variable /xsl:variable /xsl:call-template /xsl:if /xsl:call-template /xsl:if /xsl:call-template /xsl:if /xsl:call-template /xsl:if /xsl:call-template /xsl:if /xsl:call-template /xsl:if /xsl:if /xsl:if /xsl:template xsl:choose /xsl:variable /xsl:variable xsl:choose /xsl:variable /xsl:call-template /xsl:when /xsl:variable /xsl:call-template /xsl:when /xsl:choose /xsl:when xsl:otherwise /xsl:otherwise /xsl:choose /xsl:template xsl:choose /xsl:when <!-- /xsl:when --> /xsl:when /xsl:when /xsl:when /xsl:choose /xsl:call-template /xsl:if /xsl:template <!-- This template PreProcesses the input. PreProcessing involves: 1) Ensuring that all continuation ('86') type records are correcly appended to their parent records 2) Ensuring that all records end with a consistent '/' as the end of record indicator--> <!-- Ensure that all extra redundant spaces are filtered off.--> /xsl:call-template /xsl:variable /xsl:call-template /xsl:variable <!-- Any records of type ':86:' with previous record ending with 'CRLF' are a continuation of the previous record--> /xsl:call-template /xsl:variable <!-- Ajust end--> /xsl:variable /xsl:template <!-- Filter uncecessary characters around \n--> xsl:choose /xsl:call-template /xsl:call-template /xsl:when /xsl:otherwise /xsl:choose /xsl:template <!-- This is a simple string replacement helper template. It had to be written since AIF does not support XSLT 2.0 and XSLT 1.0 does not have this function built in. Parameters: txt = The text on which replacement is to be performed strToBeReplaced = The string in 'txt' that needs replacement strToReplace = The string that replaces 'strToBeReplaced' in 'txt'--> xsl:choose /xsl:call-template /xsl:when xsl:otherwise /xsl:otherwise /xsl:choose /xsl:template /xsl:call-template /xsl:template <!-- This is a helper template that is used to skip records in a given line containing comma seperated fields. The parameters are: txt = The text to skip records in recordsToSkip = The number of records to be skipped counter = A counter variable to keep track of currently skipped records in this recursive template. Helps us to get a base condition for recursion. --> xsl:choose /xsl:call-template /xsl:when xsl:otherwise /xsl:otherwise /xsl:choose /xsl:template <![CDATA[ public string isIdentificationCodeSupported(string input) { string isIdentificationCodeSupported = "No"; bool answer = input.Contains("?00") || input.Contains("?31") || input.Contains("?32") || input.Contains("?33"); if (answer == true) { isIdentificationCodeSupported = "Yes"; } return isIdentificationCodeSupported; } public string lineExtensionSectionCount(string input) { int count; count = input.Split('?').Length - 1; return count.ToString(); } public string splitNumberAndAlpha(string originalLine, string seperator) { //split the string by number and alpha, return them sepearted by seperator, and end with seperator string result = string.Empty; int i = 1; if (originalLine == null || originalLine.Length == 0) { return ""; } bool isLetter = Char.IsLetter(originalLine[0]); foreach (char c in originalLine) { bool isLetterCurrent; isLetterCurrent = Char.IsLetter(c); if (isLetterCurrent != isLetter) { result += (i++) + seperator; isLetter = isLetterCurrent; } result += c; } result += (i++) + seperator; return result; } public string splitMT940TransactionLine(string originalLine) { //split the string by number and alpha, return them sepearted by seperator, and end with seperator string result = string.Empty; int i = 1; int count = 0; bool isSkip = false; string seperator = ";"; if (originalLine == null || originalLine.Length == 0) { return ""; } bool isLetter = Char.IsLetter(originalLine[0]); foreach (char c in originalLine) { isSkip = false; if (i <= 3) { bool isLetterCurrent; isLetterCurrent = Char.IsLetter(c); if (isLetterCurrent != isLetter) { result += (i++) + seperator; isLetter = isLetterCurrent; } } else if (i <= 4) { if (count == 0) { count = 1; } count++; if (count == 5) { result += (i++) + seperator; count = 0; } } else if (i<=5) { if (c == '/') { isSkip = true; count++; } if (count == 2) { result += (i++) + seperator; count = 0; } } else if (i <= 6) { if (c == '\n') { isSkip = true; result += (i++) + seperator; } } else if (i <= 8) { if (c == '/') { count++; } if (count == 4) { result += (i++) + seperator; count = 0; } } if (!isSkip) { result += c; } } result += (i++) + seperator; return result; } public string addFileEnd(string lines) { int lastDataLine = lines.LastIndexOf("\n:"); if (lastDataLine > 0) { int lastLine = lines.IndexOf("\n", lastDataLine + 1); if (lastLine > 0) { lines = lines.Substring(0, lastLine + 1) + ":" + lines.Substring(lastLine + 1); } else { lines = lines + "\n:"; } } return lines; } ]]> /msxsl:script <![CDATA[ public string splitBySpeartors(string originalLine, string seperator, string originalSeperator1, string originalSeperator2 = "", string originalSeperator3 = "") { string line = originalLine; int i = 1; if (originalSeperator1 != null && originalSeperator1.Length > 0) { line = line.Replace(originalSeperator1, seperator); } if (originalSeperator2 != null && originalSeperator2.Length > 0) { line = line.Replace(originalSeperator2, seperator); } if (originalSeperator3 != null && originalSeperator3.Length > 0) { line = line.Replace(originalSeperator3, seperator); } if (seperator.Length == 0) { return line; } string result = string.Empty; foreach (char c in line) { if (c == seperator[0]) { result += i++; } result += c; } result += i++; result += seperator; return result; } ]]> /msxsl:script /xsl:stylesheet

Field

ESXML2RECONCILIATION-

Value -

<!-- This stylesheet converts the MT940 xml file to the schema of BankStmtISOService. -->

http://tempuri.org/BankStmtService/create xsl:apply-templates/ /xsl:template <!-- This template populates the top level table 'Document' (BankStmtISODocument) --> MT940 1 <!--The header is empty--> /xsl:template <!-- This template populates the 'AccountStatement' table (BankStmtISOAccountStatement) --> /xsl:variable /xsl:variable /xsl:value-of Reconciliation <!--Balance--> /xsl:with-param /xsl:with-param /xsl:call-template /xsl:with-param /xsl:with-param /xsl:call-template <!--Transactions--> /xsl:with-param /xsl:call-template /xsl:for-each /xsl:for-each /xsl:template <!-- This template populates the table 'CashBalance' BankStatementISOCashBalance --> /xsl:param /xsl:param /xsl:with-param /xsl:call-template /xsl:call-template /xsl:template /xsl:param /xsl:call-template /xsl:with-param /xsl:call-template /xsl:call-template xsl:choose /xsl:when xsl:otherwise /xsl:otherwise /xsl:choose /xsl:variable /xsl:with-param /xsl:call-template /xsl:with-param /xsl:call-template /xsl:if /xsl:for-each /xsl:template <!-- This template populates the table 'PartyIdentification_*' (BankStatementISOPartyIdentification) --> /xsl:template <!--Reverse Debit Credit--> xsl:choose /xsl:when xsl:otherwise /xsl:otherwise /xsl:choose /xsl:template xsl:choose /xsl:when xsl:otherwise /xsl:otherwise /xsl:choose /xsl:template xsl:choose /xsl:when /xsl:when xsl:otherwise /xsl:otherwise /xsl:choose /xsl:template <![CDATA[ public string convertToDateTime(string strDate, string strTime) { if (strDate == "") return "1900-01-01T00:00:00Z"; if (strTime == "") strTime = "0000"; string stringToConvert = strDate + strTime; DateTime dateTime = DateTime.ParseExact(stringToConvert, "yyMMddHHmm", System.Globalization.DateTimeFormatInfo.InvariantInfo); return dateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ"); } ]]> /msxsl:script /xsl:stylesheet

Field - ESRECON2COMPOSITE

Value -

/xsl:template /xsl:value-of /xsl:variable /xsl:with-param /xsl:call-template /xsl:for-each /xsl:template /xsl:param /xsl:value-of /xsl:variable /xsl:with-param /xsl:with-param /xsl:call-template /xsl:with-param /xsl:with-param /xsl:call-template /xsl:for-each /xsl:template /xsl:param /xsl:param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:call-template /xsl:for-each /xsl:template /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param xsl:choose /xsl:for-each /xsl:when xsl:otherwise 0 /xsl:otherwise /xsl:choose /xsl:template /xsl:param /xsl:param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:with-param /xsl:call-template /xsl:for-each /xsl:template /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param /xsl:param xsl:choose /xsl:for-each /xsl:when xsl:otherwise 0 /xsl:otherwise /xsl:choose /xsl:template <![CDATA[ public string trimDateTime(string strDate) { if (strDate == "") return "1900-01-01 00:00:00"; DateTime dateTime = DateTime.ParseExact(strDate, "yyyy-MM-ddTHH:mm:ssZ", System.Globalization.DateTimeFormatInfo.InvariantInfo); return dateTime.ToString("yyyy-MM-dd HH:mm:ss"); } ]]> /msxsl:script /xsl:stylesheet

Top comments (0)