Skip to content

Commit c072c4b

Browse files
the-darcChristian Sullivan
authored and
Christian Sullivan
committed
Fix support for elements with end-tags in OFX files (#37)
* Add support for elements with end-tags in OFX files * fix parse to only use arrays in child nodes if there is more than one with the same name
1 parent 0b61650 commit c072c4b

File tree

3 files changed

+172
-6
lines changed

3 files changed

+172
-6
lines changed

lib/ofx.js

+11-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* @type {[type]}
55
*/
66

7-
var parseString = require('xml2js').parseString
7+
var parser = new require('xml2js').Parser({explicitArray: false})
88
, util = require('./utils')
99
, debug = require('debug')('banking:ofx');
1010

@@ -141,13 +141,20 @@ OFX.parse = function (ofxStr, fn) {
141141
var headerString = ofxRes[0].split(/\r|\n/);
142142

143143
data.xml = ofx
144+
// Remove empty spaces and line breaks between tags
144145
.replace(/>\s+</g, '><')
146+
// Remove empty spaces and line breaks before tags content
145147
.replace(/\s+</g, '<')
148+
// Remove empty spaces and line breaks after tags content
146149
.replace(/>\s+/g, '>')
147-
.replace(/<([A-Z0-9_]*)+\.+([A-Z0-9_]*)>([^<]+)/g, '<\$1\$2>\$3' )
148-
.replace(/<(\w+?)>([^<]+)/g, '<\$1>\$2</\$1>');
150+
// Remove dots in start-tags names and remove end-tags with dots
151+
.replace(/<([A-Z0-9_]*)+\.+([A-Z0-9_]*)>([^<]+)(<\/\1\.\2>)?/g, '<\$1\$2>\$3' )
152+
// Add a new end-tags for the ofx elements
153+
.replace(/<(\w+?)>([^<]+)/g, '<\$1>\$2</<added>\$1>')
154+
// Remove duplicate end-tags
155+
.replace(/<\/<added>(\w+?)>(<\/\1>)?/g, '</\$1>');
149156

150-
parseString(data.xml, function (err, result) {
157+
parser.parseString(data.xml, function (err, result) {
151158
data.body = result;
152159
});
153160

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
OFXHEADER:100
2+
DATA:OFXSGML
3+
VERSION:102
4+
SECURITY:NONE
5+
ENCODING:USASCII
6+
CHARSET:1252
7+
COMPRESSION:NONE
8+
OLDFILEUID:NONE
9+
NEWFILEUID:NONE
10+
11+
<OFX>
12+
<SIGNONMSGSRSV1>
13+
<SONRS>
14+
<STATUS>
15+
<CODE>0</CODE>
16+
<SEVERITY>INFO</SEVERITY>
17+
</STATUS>
18+
<DTSERVER>20120127235919.500</DTSERVER>
19+
<LANGUAGE>ENG</LANGUAGE>
20+
<DTPROFUP>20050531070000.000</DTPROFUP>
21+
<FI>
22+
<ORG>WFB</ORG>
23+
<FID>3000</FID>
24+
</FI>
25+
<INTU.BID>3000</INTU.BID>
26+
<INTU.USERID>xxx34tf</INTU.USERID>
27+
</SONRS>
28+
</SIGNONMSGSRSV1>
29+
<BANKMSGSRSV1>
30+
<STMTTRNRS>
31+
<TRNUID>0</TRNUID>
32+
<STATUS>
33+
<CODE>0</CODE>
34+
<SEVERITY>INFO</SEVERITY>
35+
</STATUS>
36+
<STMTRS>
37+
<CURDEF>USD</CURDEF>
38+
<BANKACCTFROM>
39+
<BANKID>000000000</BANKID>
40+
<ACCTID>1234567890</ACCTID>
41+
<ACCTTYPE>CHECKING</ACCTTYPE>
42+
</BANKACCTFROM>
43+
<BANKTRANLIST>
44+
<DTSTART>20120101080000.000</DTSTART>
45+
<DTEND>20120126080000.000</DTEND>
46+
<STMTTRN>
47+
<TRNTYPE>DEBIT</TRNTYPE>
48+
<DTPOSTED>20120103120000.000</DTPOSTED>
49+
<TRNAMT>-49.95</TRNAMT>
50+
<FITID>201201031</FITID>
51+
<NAME>PLANET BEACH AL001</NAME>
52+
<MEMO>RECUR DEBIT CRD PMT0</MEMO>
53+
</STMTTRN>
54+
<STMTTRN>
55+
<TRNTYPE>DIRECTDEBIT</TRNTYPE>
56+
<DTPOSTED>20120105120000.000</DTPOSTED>
57+
<TRNAMT>-39.00</TRNAMT>
58+
<FITID>201201053</FITID>
59+
<NAME>CITY OF FAIRHOPE</NAME>
60+
<MEMO>UTILITIES 24-028490</MEMO>
61+
</STMTTRN>
62+
<STMTTRN>
63+
<TRNTYPE>CREDIT</TRNTYPE>
64+
<DTPOSTED>20120105120000.000</DTPOSTED>
65+
<TRNAMT>916.01</TRNAMT>
66+
<FITID>201201054</FITID>
67+
<NAME>FROM CREDIT CARD OR LINE</NAME>
68+
<MEMO>OVERDRAFT XFER</MEMO>
69+
</STMTTRN>
70+
<STMTTRN>
71+
<TRNTYPE>DIRECTDEBIT</TRNTYPE>
72+
<DTPOSTED>20120105120000.000</DTPOSTED>
73+
<TRNAMT>-3408.83</TRNAMT>
74+
<FITID>201201051</FITID>
75+
<NAME>CITY OF FAIRHOPE</NAME>
76+
<MEMO>UTILITIES 24-002394</MEMO>
77+
</STMTTRN>
78+
<STMTTRN>
79+
<TRNTYPE>DIRECTDEBIT</TRNTYPE>
80+
<DTPOSTED>20120105120000.000</DTPOSTED>
81+
<TRNAMT>-48.36</TRNAMT>
82+
<FITID>201201052</FITID>
83+
<NAME>CITY OF FAIRHOPE</NAME>
84+
<MEMO>UTILITIES 24-002393</MEMO>
85+
</STMTTRN>
86+
<STMTTRN>
87+
<TRNTYPE>DIRECTDEBIT</TRNTYPE>
88+
<DTPOSTED>20120109120000.000</DTPOSTED>
89+
<TRNAMT>-114.70</TRNAMT>
90+
<FITID>201201091</FITID>
91+
<NAME>ATT</NAME>
92+
<MEMO>Payment JUAN</MEMO>
93+
</STMTTRN>
94+
<STMTTRN>
95+
<TRNTYPE>CREDIT</TRNTYPE>
96+
<DTPOSTED>20120109120000.000</DTPOSTED>
97+
<TRNAMT>114.70</TRNAMT>
98+
<FITID>201201092</FITID>
99+
<NAME>FROM CREDIT CARD OR LINE</NAME>
100+
<MEMO>OVERDRAFT XFER</MEMO>
101+
</STMTTRN>
102+
<STMTTRN>
103+
<TRNTYPE>CREDIT</TRNTYPE>
104+
<DTPOSTED>20120112120000.000</DTPOSTED>
105+
<TRNAMT>180.69</TRNAMT>
106+
<FITID>201201122</FITID>
107+
<NAME>FROM CREDIT CARD OR LINE</NAME>
108+
<MEMO>OVERDRAFT XFER</MEMO>
109+
</STMTTRN>
110+
<STMTTRN>
111+
<TRNTYPE>DIRECTDEBIT</TRNTYPE>
112+
<DTPOSTED>20120112120000.000</DTPOSTED>
113+
<TRNAMT>-180.69</TRNAMT>
114+
<FITID>201201121</FITID>
115+
<NAME>VERIZON WIRELESS</NAME>
116+
<MEMO>PAYMENTS 120112</MEMO>
117+
</STMTTRN>
118+
<STMTTRN>
119+
<TRNTYPE>FEE</TRNTYPE>
120+
<DTPOSTED>20120125120000.000</DTPOSTED>
121+
<TRNAMT>-9.00</TRNAMT>
122+
<FITID>201201251</FITID>
123+
<NAME>MONTHLY SERVICE FEE</NAME>
124+
</STMTTRN>
125+
<STMTTRN>
126+
<TRNTYPE>CREDIT</TRNTYPE>
127+
<DTPOSTED>20120126120000.000</DTPOSTED>
128+
<TRNAMT>25.00</TRNAMT>
129+
<FITID>201201261</FITID>
130+
<NAME>FROM CREDIT CARD OR LINE</NAME>
131+
<MEMO>OVERDRAFT XFER</MEMO>
132+
</STMTTRN>
133+
</BANKTRANLIST>
134+
<LEDGERBAL>
135+
<BALAMT>16.00</BALAMT>
136+
<DTASOF>20120126080000.000[0:GMT]</DTASOF>
137+
</LEDGERBAL>
138+
<AVAILBAL>
139+
<BALAMT>16.00</BALAMT>
140+
<DTASOF>20120126080000.000[0:GMT]</DTASOF>
141+
</AVAILBAL>
142+
</STMTRS>
143+
</STMTTRNRS>
144+
</BANKMSGSRSV1>
145+
</OFX>

test/parsing.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,24 @@ describe('Banking', function(){
3838

3939
describe('.parseFile', function(){
4040
it('should read the provided file and return JSON', function(done){
41-
4241
Banking.parseFile(__dirname +'/fixtures/sample.ofx', function (res) {
4342
res.body.should.be.an.instanceof(Object);
4443
res.body.should.have.property('OFX');
44+
res.body.OFX.should.have.property('SIGNONMSGSRSV1');
45+
res.body.OFX.SIGNONMSGSRSV1.should.have.property('SONRS');
46+
res.body.OFX.SIGNONMSGSRSV1.SONRS.should.have.property('STATUS');
47+
done();
48+
});
49+
});
50+
51+
it('should read a OFX file with end-tags in elements and return JSON', function(done){
52+
Banking.parseFile(__dirname +'/fixtures/sample-with-end-tags.ofx', function (res) {
53+
res.body.should.be.an.instanceof(Object);
54+
res.body.should.have.property('OFX');
55+
res.body.should.have.property('OFX');
56+
res.body.OFX.should.have.property('SIGNONMSGSRSV1');
57+
res.body.OFX.SIGNONMSGSRSV1.should.have.property('SONRS');
58+
res.body.OFX.SIGNONMSGSRSV1.SONRS.should.have.property('STATUS');
4559
done();
4660
});
4761
});
@@ -57,4 +71,4 @@ describe('Banking', function(){
5771
});
5872
});
5973
});
60-
});
74+
});

0 commit comments

Comments
 (0)