.NETISO20022.Suite

ISO20022.Suite

Parsing, schema conversion, generation and validation in one package.

ISO20022.Suite combines the capabilities of ISO20022.XSD and ISO20022.Parser into a single .NET package. It handles XSD-to-JSON conversion, message validation, and the parsing and generation of ISO 20022 messages — so a team working with both complex XML schemas and form data has one dependency rather than three.

What it does

  • Parse ISO 20022 XML messages with pre-defined rules
  • Convert ISO 20022 XSD to a JSON form model
  • Convert form output JSON back into a valid ISO 20022 message

Install

.NET CLI
dotnet add package ISO20022.Suite
Package Manager
Install-Package ISO20022.Suite

Extract information from ISO 20022 messages

Parsing works exactly as it does in ISO20022.Parser — the Suite bundles it. Each message in a file is returned through the callback with its own identifier.

csharpParsing a pacs.008 file
using System.Data;
using ISO20022.Parser;

IParsingService parsingService = new ParsingService(
    new ParsingJsonRules(@"data\parsing_rules.json"), "Document");

await parsingService.ParseXmlAsync(@"data\pacs.008.xml",
    (DataSet ds, Guid messageUniqueId, Guid uniqueId) =>
{
    return Task.Run(() =>
    {
        foreach (DataTable dt in ds.Tables)
        {
            // Transform to CSV/Excel, or bulk-insert into a database.
            ExportDataTableToCsv(dt,
                @$"export\{messageUniqueId}_{dt.TableName}_{uniqueId}.csv");
        }
    });
});

Parsing rules

Follow the parsing rules example in the data directory of the repository. Mapping rules should follow the model class structure below.

csharp
public class MappingRules
{
    public string Namespace { get; set; }
    public List<MappingTable> Mappings { get; set; }
}

public class MappingTable
{
    public string NodeName { get; set; }
    public string XPath { get; set; }
    public IList<MappingColumn> Columns { get; set; }
}

public class MappingColumn
{
    public int OrderNumber { get; set; }
    public string NodeName { get; set; }
    public string XPath { get; set; }
    public string DataType { get; set; }
    public int MinLength { get; set; }
    public int MaxLength { get; set; }
    public int fractionDigits { get; set; }
    public int totalDigits { get; set; }
}

Override the parsing rules

The supplied example reads rules from a JSON file. To store them somewhere else — a database, say — override the ParsingRules class method DeserializeRules.

csharp
public class ParsingDatabaseRules : ParsingRules
{
    public override void DeserializeRules()
    {
        // MapParsingRules is of type IList<MappingRules>?
        MapParsingRules = GetMyRulesFromDB();
    }
}

Convert ISO 20022 XSD to JSON

Turn an ISO 20022 schema into the JSON form model that xsd-ui and ngx-xml-message render directly.

csharp
using ISO20022.XSD;

string xsdFileName = "pacs.008.001.10.xsd";
var fileInfo = new FileInfo(xsdFileName);

if (File.Exists(xsdFileName) && fileInfo.Extension.Equals(".xsd"))
{
    XsdToJson xsdLib = new(xsdFileName);
    xsdLib.Convert();
    File.AppendAllText(fileInfo.FullName.Replace(".xsd", ".json"), xsdLib.SchemaJson);
}

Convert JSON to an ISO 20022 message, and validate it

The JSON here is the output of the form components — hand it back with the target namespace and the schema, and you get a validated message.

The original swiftmx.co example declared a pacs.008 namespace while its payloads were pain.001 customer credit transfers. The namespace below matches the payload.

csharp
using ISO20022.Suite;

string targetNamespace = "urn:iso:std:iso:20022:tech:xsd:pain.001.001.12";
string jsonData = File.ReadAllText(@jsonPath);
string xsdContent = File.ReadAllText(@xsdFilePath);

XElement xml = MxMessage.Create(jsonData, targetNamespace)
    ?? throw new Exception("Conversion failed");

if (MxMessage.ValidateMXMessage(xsdContent, xml.ToString(), out string validationMessage))
{
    if (string.IsNullOrEmpty(validationMessage))
    {
        Console.WriteLine(xml?.ToString());
    }
    else
    {
        Console.Error.WriteLine(validationMessage);
    }
}
jsonForm output JSON
{
  "Document": {
    "CstmrCdtTrfInitn": {
      "GrpHdr": {
        "MsgId": "123456",
        "CreDtTm": "2025-03-27T10:00:00",
        "NbOfTxs": "1",
        "CtrlSum": "1000",
        "InitgPty": { "Nm": "Sender Company", "CtryOfRes": "US" }
      },
      "PmtInf": [
        {
          "PmtInfId": "PAY001",
          "PmtMtd": "TRF",
          "BtchBookg": "false",
          "Dbtr": { "Nm": "John Doe" },
          "DbtrAcct": { "Nm": "DE89370400440532013000" },
          "DbtrAgt": { "FinInstnId": { "BICFI": "DEUTDEFFXXX" } },
          "CdtTrfTxInf": [
            {
              "PmtId": { "EndToEndId": "TX123" },
              "Amt": { "InstdAmt": { "Ccy": "USD", "Amt": "1000" } },
              "CdtrAgt": { "FinInstnId": { "BICFI": "BNPAFRPPXXX" } },
              "Cdtr": { "Nm": "Jane Smith" },
              "CdtrAcct": { "Id": { "IBAN": "FR7630006000011234567890189" } }
            }
          ]
        }
      ]
    }
  }
}
xmlResulting message
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.12">
  <CstmrCdtTrfInitn>
    <GrpHdr>
      <MsgId>123456</MsgId>
      <CreDtTm>2025-03-27T10:00:00</CreDtTm>
      <NbOfTxs>1</NbOfTxs>
      <CtrlSum>1000</CtrlSum>
      <InitgPty>
        <Nm>Sender Company</Nm>
        <CtryOfRes>US</CtryOfRes>
      </InitgPty>
    </GrpHdr>
    <PmtInf>
      <PmtInfId>PAY001</PmtInfId>
      <PmtMtd>TRF</PmtMtd>
      <BtchBookg>false</BtchBookg>
      <Dbtr>
        <Nm>John Doe</Nm>
      </Dbtr>
      <DbtrAcct>
        <Nm>DE89370400440532013000</Nm>
      </DbtrAcct>
      <DbtrAgt>
        <FinInstnId>
          <BICFI>DEUTDEFFXXX</BICFI>
        </FinInstnId>
      </DbtrAgt>
      <CdtTrfTxInf>
        <PmtId>
          <EndToEndId>TX123</EndToEndId>
        </PmtId>
        <Amt>
          <InstdAmt Ccy="USD">1000</InstdAmt>
        </Amt>
        <CdtrAgt>
          <FinInstnId>
            <BICFI>BNPAFRPPXXX</BICFI>
          </FinInstnId>
        </CdtrAgt>
        <Cdtr>
          <Nm>Jane Smith</Nm>
        </Cdtr>
        <CdtrAcct>
          <Id>
            <IBAN>FR7630006000011234567890189</IBAN>
          </Id>
        </CdtrAcct>
      </CdtTrfTxInf>
    </PmtInf>
  </CstmrCdtTrfInitn>
</Document>
Next step

Running this in production?

We wrote these libraries and we run them. If you are planning an ISO 20022 migration, we can tell you quickly where the hard parts actually are.