ISO20022.Suite is a powerful .NET library and an all-in-one solution that combines the robust capabilities of both ISO20022.XSD and ISO20022.Parser. This comprehensive suite streamlines XSD-to-JSON conversion, message validation, as well as the parsing and generation of ISO 20022 messages—all within a single package. Whether you're working with complex XML schemas or transforming form data into ISO 20022 payment messages, ISO20022.Suite simplifies every step of the integration process, providing a unified and efficient tool for your financial messaging needs.
dotnet add package ISO20022.Suite
Install-Package ISO20022.Suite
ISO20022.Suite library help to parse or extract all the detailed information from the ISO20022 message based on predefined parsing rules.
using System.Data;
using ISO20022.Parser;
public class Program
{
private static async Task Main(string[] args)
{
IParsingService parsingService = new ParsingService(new ParsingJsonRules(@"data\parsing_rules.json"), "Document");
await parsingService.ParseXmlAsync(@"data\pacs.008.xml", (DataSet ds, Guid messageUniqueId, Guid uniquiId) =>
{
//DataSet ds: pacs.008.xml will have multiple messages in a file and this dataset will have the parsed data of the given message. Each message parsed will be callbacked over here for the further process.
// messageUniqueId : As pacs.008 will have multiple message, each message will identified with the given messageUniqueId.
// uniqueId: this id is represent the unique file Id. Meaning each passed file has been represent by the given Id.
Task task = Task.Run(() =>
{
// either we can transform to CSV/Excel or transfered to DB using bulk DB operation
string dateTime = DateTime.Now.ToString("ddmmyyyyHHmmssfff");
foreach(DataTable dt in ds.Tables)
{
ExportDataTableToCsv(dt, @$"export\{messageUniqueId}_{dt.TableName}_{uniquiId}.csv");
}
});
return task;
});
Console.Read();
}
static void ExportDataTableToCsv(DataTable dataTable, string filePath)
{
if (!File.Exists(filePath))
{
File.Create(filePath).Close();
}
// Create a StreamWriter to write to the CSV file
using (StreamWriter writer = new StreamWriter(filePath))
{
// Write the header row with column names
foreach (DataColumn column in dataTable.Columns)
{
writer.Write(column.ColumnName);
writer.Write(",");
}
writer.WriteLine(); // Move to the next line
// Write the data rows
foreach (DataRow row in dataTable.Rows)
{
foreach (object item in row.ItemArray)
{
writer.Write(item);
writer.Write(",");
}
writer.WriteLine(); // Move to the next line
}
}
}
}
Please follow the Parsing Rules example given in the data directory of the repository. Mapping Rules should follow below model class structure
public class MappingRules
{
public string Namespace { get; set; }
public List Mappings { get; set; }
}
public class MappingTable
{
public string NodeName { get; set; }
public string XPath { get; set; }
public IList 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; }
}
The given example is in json file. Suppose you want to store Parsing rules in Database. Now you need to override the ParsingRules class method DeserializeRules.
public class ParsingDatabaseRules : ParsingRules
{
public override void DeserializeRules()
{
//MapParsingRules is of type IList?
MapParsingRules = GetMyRulesFromDB();
}
}
using ISO20022.XSD;
string xsdFileName = "pacs.008.001.10.xsd";
var fileInfo = new FileInfo(xsdFileName);
if (File.Exists(fileName) && fileInfo.Extension.Equals(".xsd"))
{
XsdToJson xsdLib = new(fileName);
xsdLib.Convert();
File.AppendAllText(fileInfo.FullName.Replace(".xsd", ".json"), xsdLib.SchemaJson);
}
{
"namespace": "urn:iso:std:iso:20022:tech:xsd:pacs.008.001.10",
"schemaElement": {
"id": "Document",
"name": "Document",
"dataType": null,
"minOccurs": "1",
"maxOccurs": null,
"minLength": null,
"maxLength": null,
"pattern": null,
"fractionDigits": null,
"totalDigits": null,
"minInclusive": null,
"maxInclusive": null,
"values": null,
"isCurrency": false,
"xpath": "Document",
"elements":[
...
]
}
}
using ISO20022.Suite;
string targetNamespace = "urn:iso:std:iso:20022:tech:xsd:pacs.008.001.10";
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);
}
}
{
"Document": {
"Document_BkToCstmrStmt": {
"Document_BkToCstmrStmt_GrpHdr": {
"Document_BkToCstmrStmt_GrpHdr_MsgId": "235549650",
"Document_BkToCstmrStmt_GrpHdr_CreDtTm": "2023-10-05T14:43:51.979",
"Document_BkToCstmrStmt_GrpHdr_MsgRcpt": {
"Document_BkToCstmrStmt_GrpHdr_MsgRcpt_Nm": "Test Client Ltd.",
"Document_BkToCstmrStmt_GrpHdr_MsgRcpt_Id": {
"Document_BkToCstmrStmt_GrpHdr_MsgRcpt_Id_OrgId": {
"Document_BkToCstmrStmt_GrpHdr_MsgRcpt_Id_OrgId_Othr": [
{
"Document_BkToCstmrStmt_GrpHdr_MsgRcpt_Id_OrgId_Othr_Id": "test001"
}
]
}
}
},
"Document_BkToCstmrStmt_GrpHdr_AddtlInf": "AddTInf"
},
"Document_BkToCstmrStmt_Stmt": [
{
"Document_BkToCstmrStmt_Stmt_Id": "258158850",
"Document_BkToCstmrStmt_Stmt_ElctrncSeqNb": "1",
"Document_BkToCstmrStmt_Stmt_LglSeqNb": "1",
"Document_BkToCstmrStmt_Stmt_CreDtTm": "2023-10-05T14:43:52.098",
"Document_BkToCstmrStmt_Stmt_FrToDt": {
"Document_BkToCstmrStmt_Stmt_FrToDt_FrDtTm": "2023-09-30T20:00:00.000",
"Document_BkToCstmrStmt_Stmt_FrToDt_ToDtTm": "2023-10-01T19:59:59.000"
},
"Document_BkToCstmrStmt_Stmt_Acct": {
"Document_BkToCstmrStmt_Stmt_Acct_Tp": {
"Document_BkToCstmrStmt_Stmt_Acct_Tp_Prtry": "IBDA_DDA"
},
"Document_BkToCstmrStmt_Stmt_Acct_Ccy": "USD",
"Document_BkToCstmrStmt_Stmt_Acct_Nm": "Sample Name 123",
"Document_BkToCstmrStmt_Stmt_Acct_Svcr": {
"Document_BkToCstmrStmt_Stmt_Acct_Svcr_FinInstnId": {
"Document_BkToCstmrStmt_Stmt_Acct_Svcr_FinInstnId_BICFI": "GSCRUS30",
"Document_BkToCstmrStmt_Stmt_Acct_Svcr_FinInstnId_Nm": "Goldman Sachs Bank"
}
}
},
"Document_BkToCstmrStmt_Stmt_Bal": [
{
"Document_BkToCstmrStmt_Stmt_Bal_Tp": {
"Document_BkToCstmrStmt_Stmt_Bal_Tp_CdOrPrtry": {
"Document_BkToCstmrStmt_Stmt_Bal_Tp_CdOrPrtry_Cd": "OPBD"
}
},
"Document_BkToCstmrStmt_Stmt_Bal_Amt": {
"Document_BkToCstmrStmt_Stmt_Bal_Amt_Ccy": "USD",
"Document_BkToCstmrStmt_Stmt_Bal_Amt_Amt": "843686.20"
},
"Document_BkToCstmrStmt_Stmt_Bal_CdtDbtInd": "DBIT",
"Document_BkToCstmrStmt_Stmt_Bal_Dt": {
"Document_BkToCstmrStmt_Stmt_Bal_Dt_DtTm": "2023-09-30T20:00:00.000"
}
},
{
"Document_BkToCstmrStmt_Stmt_Bal_Tp": {
"Document_BkToCstmrStmt_Stmt_Bal_Tp_CdOrPrtry": {
"Document_BkToCstmrStmt_Stmt_Bal_Tp_CdOrPrtry_Cd": "CLAV"
}
},
"Document_BkToCstmrStmt_Stmt_Bal_Amt": {
"Document_BkToCstmrStmt_Stmt_Bal_Amt_Ccy": "USD",
"Document_BkToCstmrStmt_Stmt_Bal_Amt_Amt": "334432401.27"
},
"Document_BkToCstmrStmt_Stmt_Bal_CdtDbtInd": "CRDT",
"Document_BkToCstmrStmt_Stmt_Bal_Dt": {
"Document_BkToCstmrStmt_Stmt_Bal_Dt_DtTm": "2023-10-01T23:59:00.000Z"
}
}
]
}
]
}
}
}
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.10">
<BkToCstmrStmt>
<GrpHdr>
<MsgId>235549650</MsgId>
<CreDtTm>2023-10-05T14:43:51.979</CreDtTm>
<MsgRcpt>
<Nm>Test Client Ltd.</Nm>
<Id>
<OrgId>
<Othr>
<Id>test001</Id>
</Othr>
</OrgId>
</Id>
</MsgRcpt>
<AddtlInf>AddTInf</AddtlInf>
</GrpHdr>
<Stmt>
<Id>258158850</Id>
<ElctrncSeqNb>1</ElctrncSeqNb>
<LglSeqNb>1</LglSeqNb>
<CreDtTm>2023-10-05T14:43:52.098</CreDtTm>
<FrToDt>
<FrDtTm>2023-09-30T20:00:00.000</FrDtTm>
<ToDtTm>2023-10-01T19:59:59.000</ToDtTm>
</FrToDt>
<Acct>
<Tp>
<Prtry>IBDA_DDA</Prtry>
</Tp>
<Ccy>USD</Ccy>
<Nm>Sample Name 123</Nm>
<Svcr>
<FinInstnId>
<BICFI>GSCRUS30</BICFI>
<Nm>Goldman Sachs Bank</Nm>
</FinInstnId>
</Svcr>
</Acct>
<Bal>
<Tp>
<CdOrPrtry>
<Cd>OPBD</Cd>
</CdOrPrtry>
</Tp>
<Amt Ccy="USD">843686.20</Amt>
<CdtDbtInd>DBIT</CdtDbtInd>
<Dt>
<DtTm>2023-09-30T20:00:00.000</DtTm>
</Dt>
</Bal>
<Bal>
<Tp>
<CdOrPrtry>
<Cd>CLAV</Cd>
</CdOrPrtry>
</Tp>
<Amt Ccy="USD">334432401.27</Amt>
<CdtDbtInd>CRDT</CdtDbtInd>
<Dt>
<DtTm>2023-10-01T23:59:00.000Z</DtTm>
</Dt>
</Bal>
</Stmt>
</BkToCstmrStmt>
</Document>