Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse multiple tags on the same line of ofx file #17

Merged
merged 4 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 41 additions & 7 deletions src/OfxNet/Sgml/SgmlParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class SgmlParser
private int lineNumber;
private SgmlElement root = SgmlElement.Empty;
private SgmlElement currentNode = SgmlElement.Empty;
private SgmlElement lastValueNode = SgmlElement.Empty;

/// <summary>
/// Parse teh specified file as an SGML formatted OFX document.
Expand All @@ -32,15 +33,39 @@ public SgmlElement Parse(string path, Encoding encoding)
var line = reader.ReadLine();
++this.lineNumber;

if (string.IsNullOrWhiteSpace(line) == false)
if (string.IsNullOrEmpty(line) == false)
{
this.ProcessLine(line);
var tags = line.Split("<");
foreach (string tag in tags)
{
if (string.IsNullOrWhiteSpace(tag) == false)
{
this.ProcessLine(Wellformed(tag));
}
}
}
}

return this.root;
}

private static string Wellformed(string tag)
{
if (tag.Contains('<', StringComparison.Ordinal) &&
tag.Contains('>', StringComparison.Ordinal))
{
return tag;
}
else if (tag.Contains('>', StringComparison.Ordinal))
{
return "<" + tag;
}
else
{
return tag;
}
}

private static SgmlParseResult? TryParseOpeningTag(string line)
{
SgmlParseResult? result = default;
Expand Down Expand Up @@ -162,17 +187,26 @@ private void ProcessValueTag(string tag, string? value, string text)
{
value = GetValue(value);

this.currentNode.AddChild(new SgmlElement(tag, value, text, this.currentNode));
this.lastValueNode = this.currentNode.AddChild(new SgmlElement(tag, value, text, this.currentNode));
}

private void ProcessClosingTag(string tag)
{
string expectedTag = this.currentNode.Name;
if (string.Equals(expectedTag, tag, StringComparison.OrdinalIgnoreCase) == false)
string expectedvalueTag = this.lastValueNode.Name;

if (string.Equals(expectedTag, tag, StringComparison.OrdinalIgnoreCase))
{
throw new SgmlParseException($"Closing tag '{tag}' does not match opening tag '{expectedTag}', line {this.lineNumber}.");
this.currentNode = this.currentNode.Parent ?? this.root;
}
else if (string.Equals(expectedvalueTag, tag, StringComparison.OrdinalIgnoreCase))
{
// value node has closing tag, so we don't expect it anymore, current node does not change
this.lastValueNode = SgmlElement.Empty;
}
else
{
throw new SgmlParseException($"Closing tag '{tag}' does not match opening tag '{expectedTag}' or '{expectedvalueTag}', line {this.lineNumber}.");
}

this.currentNode = this.currentNode.Parent ?? this.root;
}
}
6 changes: 5 additions & 1 deletion test/OfxNet.IntegrationTests/OfxDocumentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Microsoft;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
Expand All @@ -22,6 +21,11 @@ public static IEnumerable<object[]> SampleOfxFiles
yield return new object[] { "Sample-itau.ofx", 1, 3 };
yield return new object[] { "Sample-santander.ofx", 1, 3 };
yield return new object[] { "Sample-Banco do Brasil.ofx", 1, 3 };

// added to test multi-tags per line
yield return new object[] { "SampleBankStatement_tangerine.ofx", 1, 0 };
yield return new object[] { "SampleBankStatement_cibc.ofx", 1, 6 };
yield return new object[] { "SampleCreditCardStatement_cibc.ofx", 1, 4 };
}
}

Expand Down
22 changes: 22 additions & 0 deletions test/OfxNet.IntegrationTests/SampleBankStatement_cibc.ofx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
OFXHEADER:100
DATA:OFXSGML
VERSION:102
SECURITY:NONE
ENCODING:USASCII
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE

<OFX><SIGNONMSGSRSV1><SONRS><STATUS><CODE>0<SEVERITY>INFO<MESSAGE>OK</STATUS><DTSERVER>20231219105650<LANGUAGE>ENG<DTPROFUP>20231219105650<DTACCTUP>20231219105650<INTU.BID>00005</SONRS></SIGNONMSGSRSV1>
<BANKMSGSRSV1><STMTTRNRS><TRNUID>20231219105650<STATUS><CODE>0<SEVERITY>INFO<MESSAGE>OK</STATUS>
<STMTRS><CURDEF>CAD<BANKACCTFROM><BANKID>600000100<ACCTID>00502 99-9999<ACCTTYPE>SAVINGS</BANKACCTFROM>
<BANKTRANLIST><DTSTART>20231215120000<DTEND>20231218120000
<STMTTRN><TRNTYPE>DEBIT<DTPOSTED>20231218120000.000[-5:EST]<TRNAMT>-8.50<FITID>23352352113424231137000001<NAME>A&amp;W RESTAURANT<MEMO>RETAIL PURCHASE 000001754018;Point of Sale - Interac</STMTTRN>
<STMTTRN><TRNTYPE>DEBIT<DTPOSTED>20231218120000.000[-5:EST]<TRNAMT>-5000.00<FITID>23352350140921446806000001<MEMO>INTERNET TRANSFER 000000237456;Internet Banking</STMTTRN>
<STMTTRN><TRNTYPE>DEBIT<DTPOSTED>20231218120000.000[-5:EST]<TRNAMT>-69.69<FITID>23352350135316167792000001<NAME>BELL CANADA BUSINESS (16-<MEMO>INTERNET BILL PAY 000000108757;Internet Banking</STMTTRN>
<STMTTRN><TRNTYPE>DEBIT<DTPOSTED>20231218120000.000[-5:EST]<TRNAMT>-999.44<FITID>23352350135316117189000001<NAME>MASTERCARD, XXX<MEMO>INTERNET BILL PAY 000000108756;Internet Banking</STMTTRN>
<STMTTRN><TRNTYPE>DEBIT<DTPOSTED>20231218120000.000[-5:EST]<TRNAMT>-75.63<FITID>23352350135316055740000001<NAME>PhoneCo<MEMO>INTERNET BILL PAY 000000108755;Internet Banking</STMTTRN>
<STMTTRN><TRNTYPE>CREDIT<DTPOSTED>20231215120000.000[-5:EST]<TRNAMT>2345.67<FITID>23349349031321161745750000<MEMO>PAY;10632921088;SomeCompANY;Electronic Funds Transfer</STMTTRN>
</BANKTRANLIST>
<LEDGERBAL><BALAMT>11790.00<DTASOF>20231219105650</LEDGERBAL><AVAILBAL><BALAMT>11790.00<DTASOF>20231219105650</AVAILBAL></STMTRS></STMTTRNRS></BANKMSGSRSV1></OFX>
11 changes: 11 additions & 0 deletions test/OfxNet.IntegrationTests/SampleBankStatement_tangerine.ofx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
OFXHEADER:100
DATA:OFXSGML
VERSION:102
SECURITY:NONE
ENCODING:USASCII
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE

<OFX><SIGNONMSGSRSV1><SONRS><STATUS><CODE>0<SEVERITY>INFO<MESSAGE>Authentication Successful.</STATUS><DTSERVER>20231222141903.628[-5:EST]<LANGUAGE>ENG<FI><ORG>Tangerine<FID>061400152</FI></SONRS></SIGNONMSGSRSV1><BANKMSGSRSV1><STMTTRNRS><TRNUID>0<STATUS><CODE>0<SEVERITY>INFO</STATUS><STMTRS><CURDEF>CAD<BANKACCTFROM><BANKID>0614<ACCTID>3004345436<ACCTTYPE>SAVINGS</BANKACCTFROM><BANKTRANLIST><DTSTART>20231221190000.000[-5:EST]<DTEND>20231221190000.000[-5:EST]</BANKTRANLIST><LEDGERBAL><BALAMT>104651.63<DTASOF>20231222141903.628[-5:EST]</LEDGERBAL><AVAILBAL><BALAMT>2222222.63<DTASOF>20231222141903.628[-5:EST]</AVAILBAL></STMTRS></STMTTRNRS></BANKMSGSRSV1></OFX>
26 changes: 26 additions & 0 deletions test/OfxNet.IntegrationTests/SampleCreditCardStatement_cibc.ofx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
OFXHEADER:100
DATA:OFXSGML
VERSION:102
SECURITY:NONE
ENCODING:USASCII
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE

<OFX>
<SIGNONMSGSRSV1><SONRS><STATUS><CODE>0<SEVERITY>INFO<MESSAGE>OK</STATUS><DTSERVER>20231219105825<LANGUAGE>ENG<DTPROFUP>20231219105825<DTACCTUP>20231219105825<INTU.BID>00005</SONRS>
</SIGNONMSGSRSV1>
<CREDITCARDMSGSRSV1>
<CCSTMTTRNRS><TRNUID>20231219105825<STATUS><CODE>0<SEVERITY>INFO<MESSAGE>OK</STATUS><CCSTMTRS><CURDEF>CAD<CCACCTFROM>
<ACCTID>4505530099999999<ACCTTYPE>CREDITLINE</CCACCTFROM>
<BANKTRANLIST>
<DTSTART>20231215120000<DTEND>20231215120000<STMTTRN><TRNTYPE>DEBIT<DTPOSTED>20231215120000.000[-5:EST]<TRNAMT>-91.50<FITID>202334900570278<NAME>PET VALU CANADA INC<MEMO>MARKHAM, ON;CC#4505********9999</STMTTRN>
<STMTTRN><TRNTYPE>DEBIT<DTPOSTED>20231215120000.000[-5:EST]<TRNAMT>-65.86<FITID>202334900570277<NAME>SHOPPERS DRUG MART #14<MEMO>ETOBICOKE, ON;CC#4505********8888</STMTTRN>
<STMTTRN><TRNTYPE>DEBIT<DTPOSTED>20231215120000.000[-5:EST]<TRNAMT>-97.33<FITID>202334900570276<NAME>FARM BOY #24<MEMO>TORONTO, ON;CC#4505********9999</STMTTRN>
<STMTTRN><TRNTYPE>DEBIT<DTPOSTED>20231215120000.000[-5:EST]<TRNAMT>-47.63<FITID>202334900570275<NAME>GIANT TIGER #168<MEMO>ETOBICOKE, ON;CC#4505********9999</STMTTRN>
</BANKTRANLIST>
<LEDGERBAL><BALAMT>-3863.64<DTASOF>20231219105825</LEDGERBAL>
<AVAILBAL><BALAMT>18563.89<DTASOF>20231219105825</AVAILBAL>
</CCSTMTRS></CCSTMTTRNRS></CREDITCARDMSGSRSV1>
</OFX>