【问题标题】:Swift MT940 parser in C#C# 中的 Swift MT940 解析器
【发布时间】:2020-04-17 14:05:24
【问题描述】:

如何使用 C# 解析 MT940 swift 消息?
以下是我必须解析的消息:

:20:MT940-1411201901
:25:1234567837710016 
:28C:008/201
:60F:C171224SAR145597,13
:61:2107221722D17000,NCHK219120//14218-102431Abnamb
:61:2107221722D17000,NCHK219120//14218-102431Abnamb VSP
:62F:C291124SAR145597,13

我怎么能意识到这一点?

【问题讨论】:

  • 这不是真正的 Swift 消息,因为没有可用的标头。我可以建议您将其解析为^:\d\d\w?:.*。但是您必须检查是否正确解析了多行字段。另请注意,一些 swift 消息可以在字段值中包含诸如 :20: 之类的字段代码,因此您必须预测此类情况
  • 这不是 XML,即使数据类型被称为标签。请参阅:sepaforcorporates.com/swift-for-corporates/…

标签: c# xml xml-parsing b2b mt940


【解决方案1】:

试试下面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using System.Globalization;

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.txt";
        static void Main(string[] args)
        {
            MT940 mt940 = new MT940(FILENAME);
        }
    }
    public class MT940
    {
        const string TAG_PATTERN = @"^:(?'tag'[^:]+):(?'value'.*)";

        public string senderReference { get; set; }  //code 20
        public string authorisation { get; set; } // tag 25
        public string messageIndexTotal { get; set; } //tag 28D
        public Currency openingBalance { get; set; }  //60F
        public string firstTransaction { get; set; } //61
        public string secondTransaction { get; set; } //61
        public Currency closingBalance { get; set; } //62F

        public MT940(string filename)
        {
            StreamReader reader = new StreamReader(filename);
            string line = "";
            int transactionCount = 0;

            while ((line = reader.ReadLine()) != null)
            {
                if (line.StartsWith(":"))
                {
                    Match match = Regex.Match(line, TAG_PATTERN);
                    string tag = match.Groups["tag"].Value;
                    string value = match.Groups["value"].Value;

                    switch (tag)
                    {
                        case "20":
                            senderReference = value;
                            break;

                        case "25":
                            authorisation = value;
                            break;

                        case "28C":
                            messageIndexTotal = value;
                            break;

                        case "60F":
                            openingBalance = new Currency(value);
                            break;
                        case "61":
                            if (++transactionCount == 1)
                            {
                                firstTransaction = value;
                            }
                            else
                            {
                                secondTransaction = value;
                            }
                            break;

                        case "62F":
                            closingBalance = new Currency(value);
                            break;
                        default:
                            break;
                    }
                }
            }
        }

    }
    public class Currency
    {
        const string BALANCE_PATTERN = @"^(?'credit_debit'.)(?'date'.{6})(?'country_code'.{3})(?'amount'.*)";
        static CultureInfo culture = CultureInfo.GetCultureInfoByIetfLanguageTag("da");

        public DateTime date { get; set; }
        public string currencyCode { get; set; }
        public decimal amount { get; set; }

        public Currency(string input)
        {
            Match match = Regex.Match(input, BALANCE_PATTERN);

            string credit_debit = match.Groups["credit_debit"].Value;

            string dateStr = match.Groups["date"].Value;
            date = DateTime.ParseExact(dateStr, "yyMMdd", CultureInfo.InvariantCulture);

            currencyCode = match.Groups["country_code"].Value;

            string amountStr = match.Groups["amount"].Value;
            amount = decimal.Parse(amountStr, culture);
            amount *= credit_debit == "D" ? -1 : 1;
        }
    }
}

【讨论】:

  • 要正确编写解析器,您必须了解业务规则。 940 消息可以包含很多 61 个字段(超过两个)。 61 字段也可以be followed by the 86 field。 86 是多行字段,因此逐行读取文件有点棘手。示例代码解析提供但在真实 MT940 上失败的特定示例。解析 Swift MT 格式需要良好的知识,而且远远超出 SA 应提供的知识。
  • line.Split(new char[] {':'} 将丢失字段值,如果它包含 ':' 字符,如:86:the reason: to return funds
  • @oleksa :您提供的链接未指定字段可以包含冒号。可以提供参考吗?
  • 好吧,86字段没有任何限制,可以包含':'。 61 实际上是多行字段,可以在新行上有Supplementary Details。 Swift 消息解析意味着必须将字段 61(例如)解析为 Value date、Entry date、Amoun、Code、Number、Reference 必填字段。有太多隐藏的宝石无法使用 SO 解析 Swift MT。这个问题最终可以作为学生教育的一部分使用 SO 解决,但不能用于生产代码
  • 除非必要,否则我不喜欢使用正则表达式。我更喜欢更有效的字符串方法。我将更改代码。
猜你喜欢
  • 2011-04-19
  • 2014-06-18
  • 1970-01-01
  • 2016-10-19
  • 2020-01-16
  • 2012-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多