29 #include "ParserEventGeneratorKit.h"
38 extern SGMLApplication::OpenEntityPtr
entity_ptr;
39 extern SGMLApplication::Position
position;
40 static const std::string MESSAGE_NON_SGML_CHAR =
"non SGML character";
51 std::string incoming_data;
53 unsigned errorCountToIgnore = 0;
60 curr_container_element = NULL;
61 is_data_element =
false;
62 libofx_context = p_libofx_context;
69 unsigned getErrorCountToIgnore()
const {
return errorCountToIgnore; }
78 message_out(
PARSER,
"startElement event received from OpenSP for element " + identifier);
82 switch (event.contentType)
84 case StartElementEvent::empty:
87 case StartElementEvent::cdata:
90 case StartElementEvent::rcdata:
93 case StartElementEvent::mixed:
95 is_data_element =
true;
97 case StartElementEvent::element:
99 is_data_element =
false;
102 message_out(
ERROR,
"Unknown SGML content type?!?!?!? OpenSP interface changed?");
105 if (is_data_element ==
false)
109 if (identifier ==
"OFX")
112 MainContainer =
new OfxMainContainer (libofx_context, curr_container_element, identifier);
113 curr_container_element = MainContainer;
115 else if (identifier ==
"STATUS")
118 curr_container_element =
new OfxStatusContainer (libofx_context, curr_container_element, identifier);
120 else if (identifier ==
"STMTRS" ||
121 identifier ==
"CCSTMTRS" ||
122 identifier ==
"INVSTMTRS")
125 curr_container_element =
new OfxStatementContainer (libofx_context, curr_container_element, identifier);
127 else if (identifier ==
"BANKTRANLIST" || identifier ==
"INVTRANLIST")
131 if (curr_container_element && curr_container_element->
type !=
"STATEMENT")
133 message_out(
ERROR,
"Element " + identifier +
" found while not inside a STATEMENT container");
137 curr_container_element =
new OfxPushUpContainer (libofx_context, curr_container_element, identifier);
140 else if (identifier ==
"STMTTRN")
143 if (curr_container_element && curr_container_element->
type ==
"INVESTMENT")
146 curr_container_element =
new OfxPushUpContainer (libofx_context, curr_container_element, identifier);
153 else if (identifier ==
"BUYDEBT" ||
154 identifier ==
"BUYMF" ||
155 identifier ==
"BUYOPT" ||
156 identifier ==
"BUYOTHER" ||
157 identifier ==
"BUYSTOCK" ||
158 identifier ==
"CLOSUREOPT" ||
159 identifier ==
"INCOME" ||
160 identifier ==
"INVEXPENSE" ||
161 identifier ==
"JRNLFUND" ||
162 identifier ==
"JRNLSEC" ||
163 identifier ==
"MARGININTEREST" ||
164 identifier ==
"REINVEST" ||
165 identifier ==
"RETOFCAP" ||
166 identifier ==
"SELLDEBT" ||
167 identifier ==
"SELLMF" ||
168 identifier ==
"SELLOPT" ||
169 identifier ==
"SELLOTHER" ||
170 identifier ==
"SELLSTOCK" ||
171 identifier ==
"SPLIT" ||
172 identifier ==
"TRANSFER" ||
173 identifier ==
"INVBANKTRAN" )
179 else if (identifier ==
"INVBUY" ||
180 identifier ==
"INVSELL" ||
181 identifier ==
"INVTRAN" ||
182 identifier ==
"SECINFO" ||
183 identifier ==
"SECID" ||
184 identifier ==
"CURRENCY" ||
185 identifier ==
"ORIGCURRENCY")
188 curr_container_element =
new OfxPushUpContainer (libofx_context, curr_container_element, identifier);
192 else if (identifier ==
"BANKACCTINFO" || identifier ==
"CCACCTINFO" || identifier ==
"INVACCTINFO")
195 curr_container_element =
new OfxPushUpContainer (libofx_context, curr_container_element, identifier);
199 else if (identifier ==
"BANKACCTFROM" || identifier ==
"CCACCTFROM" || identifier ==
"INVACCTFROM")
203 if (curr_container_element &&
204 ( curr_container_element->
type ==
"STATEMENT"
208 curr_container_element =
new OfxAccountContainer (libofx_context, curr_container_element, identifier);
211 curr_container_element =
new OfxDummyContainer (libofx_context, curr_container_element, identifier);
213 else if (identifier ==
"STOCKINFO" || identifier ==
"OPTINFO" ||
214 identifier ==
"DEBTINFO" || identifier ==
"MFINFO" || identifier ==
"OTHERINFO")
217 curr_container_element =
new OfxSecurityContainer (libofx_context, curr_container_element, identifier);
220 else if (identifier ==
"LEDGERBAL" ||
221 identifier ==
"AVAILBAL" ||
222 identifier ==
"INVBAL")
225 curr_container_element =
new OfxBalanceContainer (libofx_context, curr_container_element, identifier);
227 else if (identifier ==
"INVPOS")
230 curr_container_element =
new OfxPositionContainer (libofx_context, curr_container_element, identifier);
235 curr_container_element =
new OfxDummyContainer(libofx_context, curr_container_element, identifier);
242 if (identifier ==
"INV401K")
246 curr_container_element =
new OfxInv401kContainer (libofx_context, curr_container_element, identifier);
248 if (identifier ==
"INV401KBAL")
251 curr_container_element =
new OfxBalanceContainer (libofx_context, curr_container_element, identifier);
258 if (incoming_data !=
"")
260 message_out (
ERROR,
"startElement: incoming_data should be empty! You are probably using OpenSP <= 1.3.4. The following data was lost: " + incoming_data );
261 incoming_data.assign (
"");
274 bool end_element_for_data_element = is_data_element;
275 message_out(
PARSER,
"endElement event received from OpenSP for element " + identifier);
278 if (curr_container_element == NULL)
280 message_out (
ERROR,
"Tried to close a " + identifier +
" without a open element (NULL pointer)");
281 incoming_data.assign (
"");
285 if (end_element_for_data_element ==
true)
289 curr_container_element->
add_attribute (identifier, incoming_data);
290 message_out (
PARSER,
"endElement: Added data '" + incoming_data +
"' from " + identifier +
" to " + curr_container_element->
type +
" container_element");
291 incoming_data.assign (
"");
292 is_data_element =
false;
298 if (incoming_data !=
"")
300 message_out(
ERROR,
"End tag for non data element " + identifier +
", incoming data should be empty but contains: " + incoming_data +
" DATA HAS BEEN LOST SOMEWHERE!");
303 if (identifier ==
"OFX")
306 tmp_container_element = curr_container_element;
307 curr_container_element = curr_container_element->
getparent ();
308 if (curr_container_element == NULL)
311 curr_container_element = tmp_container_element;
313 if (MainContainer != NULL)
316 delete MainContainer;
317 MainContainer = NULL;
318 curr_container_element = NULL;
319 message_out (
DEBUG,
"Element " + identifier +
" closed, MainContainer destroyed");
323 message_out (
DEBUG,
"Element " + identifier +
" closed, but there was no MainContainer to destroy (probably a malformed file)!");
328 tmp_container_element = curr_container_element;
329 curr_container_element = curr_container_element->
getparent ();
330 if (MainContainer != NULL)
335 if (identifier ==
"CURRENCY" || identifier ==
"ORIGCURRENCY")
337 tmp_container_element->
add_attribute (identifier, incoming_data);
338 message_out (
DEBUG,
"Element " + identifier +
" closed, container " + tmp_container_element->
type +
" updated");
343 message_out (
PARSER,
"Element " + identifier +
" closed, object added to MainContainer");
348 message_out (
ERROR,
"MainContainer is NULL trying to add element " + identifier);
354 message_out (
ERROR,
"Tried to close a " + identifier +
" but a " + curr_container_element->
type +
" is currently open.");
364 void data (
const DataEvent & event)
369 message_out(
PARSER,
"data event received from OpenSP, incoming_data is now: " + incoming_data);
376 void error (
const ErrorEvent & event)
383 message = message +
"OpenSP parser: ";
386 case SGMLApplication::ErrorEvent::quantity:
387 message = message +
"quantity (Exceeding a quantity limit):";
390 case SGMLApplication::ErrorEvent::idref:
391 message = message +
"idref (An IDREF to a non-existent ID):";
394 case SGMLApplication::ErrorEvent::capacity:
395 message = message +
"capacity (Exceeding a capacity limit):";
398 case SGMLApplication::ErrorEvent::otherError:
403 if (eventMessage.find(MESSAGE_NON_SGML_CHAR) != std::string::npos) {
404 ++errorCountToIgnore;
405 message = message +
"ignored character error:";
408 message = message +
"otherError (misc parse error):";
412 case SGMLApplication::ErrorEvent::warning:
413 message = message +
"warning (Not actually an error.):";
416 case SGMLApplication::ErrorEvent::info:
417 message = message +
"info (An informationnal message. Not actually an error):";
421 message = message +
"OpenSP sent an unknown error to LibOFX (You probably have a newer version of OpenSP):";
423 message = message +
"\n" + eventMessage;
452 ParserEventGeneratorKit parserKit;
453 parserKit.setOption (ParserEventGeneratorKit::showOpenEntities);
454 EventGenerator *egp = parserKit.makeEventGenerator (argc, argv);
455 egp->inhibitMessages (
true);
457 unsigned originalErrorCount = egp->run (app);
458 unsigned nErrors = originalErrorCount - app.getErrorCountToIgnore();