Branch data Line data Source code
1 : : /********************************************************************
2 : : * gnc-transactions-xml-v2.c -- xml routines for transactions *
3 : : * Copyright (C) 2001 Rob Browning *
4 : : * Copyright (C) 2002 Linas Vepstas <linas@linas.org> *
5 : : * *
6 : : * This program is free software; you can redistribute it and/or *
7 : : * modify it under the terms of the GNU General Public License as *
8 : : * published by the Free Software Foundation; either version 2 of *
9 : : * the License, or (at your option) any later version. *
10 : : * *
11 : : * This program is distributed in the hope that it will be useful, *
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 : : * GNU General Public License for more details. *
15 : : * *
16 : : * You should have received a copy of the GNU General Public License*
17 : : * along with this program; if not, contact: *
18 : : * *
19 : : * Free Software Foundation Voice: +1-617-542-5942 *
20 : : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21 : : * Boston, MA 02110-1301, USA gnu@gnu.org *
22 : : * *
23 : : *******************************************************************/
24 : : #include <glib.h>
25 : :
26 : : #include <config.h>
27 : : #include <string.h>
28 : : #include "AccountP.hpp"
29 : : #include "Transaction.h"
30 : : #include "TransactionP.hpp"
31 : : #include "gnc-lot.h"
32 : : #include "gnc-lot-p.h"
33 : :
34 : : #include "gnc-xml-helper.h"
35 : :
36 : : #include "sixtp.h"
37 : : #include "sixtp-utils.h"
38 : : #include "sixtp-parsers.h"
39 : : #include "sixtp-utils.h"
40 : : #include "sixtp-dom-parsers.h"
41 : : #include "sixtp-dom-generators.h"
42 : :
43 : : #include "gnc-xml.h"
44 : :
45 : : #include "io-gncxml-gen.h"
46 : :
47 : : #include "sixtp-dom-parsers.h"
48 : :
49 : : [[maybe_unused]] static const QofLogModule log_module = G_LOG_DOMAIN;
50 : : const gchar* transaction_version_string = "2.0.0";
51 : :
52 : : static void
53 : 232 : add_gnc_num (xmlNodePtr node, const gchar* tag, gnc_numeric num)
54 : : {
55 : 232 : xmlAddChild (node, gnc_numeric_to_dom_tree (tag, &num));
56 : 232 : }
57 : :
58 : : static void
59 : 232 : add_time64 (xmlNodePtr node, const gchar * tag, time64 time, gboolean always)
60 : : {
61 : 232 : if (always || time)
62 : 216 : xmlAddChild (node, time64_to_dom_tree (tag, time));
63 : 232 : }
64 : :
65 : : static xmlNodePtr
66 : 116 : split_to_dom_tree (const gchar* tag, Split* spl)
67 : : {
68 : : xmlNodePtr ret;
69 : :
70 : 116 : ret = xmlNewNode (NULL, BAD_CAST tag);
71 : :
72 : 116 : xmlAddChild (ret, guid_to_dom_tree ("split:id", xaccSplitGetGUID (spl)));
73 : :
74 : : {
75 : 116 : char* memo = g_strdup (xaccSplitGetMemo (spl));
76 : :
77 : 116 : if (memo && g_strcmp0 (memo, "") != 0)
78 : : {
79 : 104 : xmlNewTextChild (ret, NULL, BAD_CAST "split:memo",
80 : 104 : checked_char_cast (memo));
81 : : }
82 : 116 : g_free (memo);
83 : : }
84 : :
85 : : {
86 : 116 : char* action = g_strdup (xaccSplitGetAction (spl));
87 : :
88 : 116 : if (action && g_strcmp0 (action, "") != 0)
89 : : {
90 : 104 : xmlNewTextChild (ret, NULL, BAD_CAST "split:action",
91 : 104 : checked_char_cast (action));
92 : : }
93 : 116 : g_free (action);
94 : : }
95 : :
96 : : {
97 : : char tmp[2];
98 : :
99 : 116 : tmp[0] = xaccSplitGetReconcile (spl);
100 : 116 : tmp[1] = '\0';
101 : :
102 : 116 : xmlNewTextChild (ret, NULL, BAD_CAST "split:reconciled-state",
103 : : BAD_CAST tmp);
104 : : }
105 : :
106 : 116 : add_time64 (ret, "split:reconcile-date",
107 : : xaccSplitGetDateReconciled (spl), FALSE);
108 : :
109 : 116 : add_gnc_num (ret, "split:value", xaccSplitGetValue (spl));
110 : :
111 : 116 : add_gnc_num (ret, "split:quantity", xaccSplitGetAmount (spl));
112 : :
113 : : {
114 : 116 : Account* account = xaccSplitGetAccount (spl);
115 : :
116 : 116 : xmlAddChild (ret, guid_to_dom_tree ("split:account",
117 : 116 : xaccAccountGetGUID (account)));
118 : : }
119 : : {
120 : 116 : GNCLot* lot = xaccSplitGetLot (spl);
121 : :
122 : 116 : if (lot)
123 : : {
124 : 2 : xmlAddChild (ret, guid_to_dom_tree ("split:lot",
125 : 2 : gnc_lot_get_guid (lot)));
126 : : }
127 : : }
128 : : /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
129 : 116 : xmlAddChild (ret, qof_instance_slots_to_dom_tree ("split:slots",
130 : 116 : QOF_INSTANCE (spl)));
131 : 116 : return ret;
132 : : }
133 : :
134 : : static void
135 : 58 : add_trans_splits (xmlNodePtr node, Transaction* trn)
136 : : {
137 : : GList* n;
138 : : xmlNodePtr toaddto;
139 : :
140 : 58 : toaddto = xmlNewChild (node, NULL, BAD_CAST "trn:splits", NULL);
141 : :
142 : 174 : for (n = xaccTransGetSplitList (trn); n; n = n->next)
143 : : {
144 : 116 : Split* s = static_cast<decltype (s)> (n->data);
145 : 116 : xmlAddChild (toaddto, split_to_dom_tree ("trn:split", s));
146 : : }
147 : 58 : }
148 : :
149 : : xmlNodePtr
150 : 58 : gnc_transaction_dom_tree_create (Transaction* trn)
151 : : {
152 : : xmlNodePtr ret;
153 : 58 : gchar* str = NULL;
154 : :
155 : 58 : ret = xmlNewNode (NULL, BAD_CAST "gnc:transaction");
156 : :
157 : 58 : xmlSetProp (ret, BAD_CAST "version",
158 : : BAD_CAST transaction_version_string);
159 : :
160 : 58 : xmlAddChild (ret, guid_to_dom_tree ("trn:id", xaccTransGetGUID (trn)));
161 : :
162 : 58 : xmlAddChild (ret, commodity_ref_to_dom_tree ("trn:currency",
163 : 58 : xaccTransGetCurrency (trn)));
164 : 58 : str = g_strdup (xaccTransGetNum (trn));
165 : 58 : if (str && (g_strcmp0 (str, "") != 0))
166 : : {
167 : 52 : xmlNewTextChild (ret, NULL, BAD_CAST "trn:num",
168 : 52 : checked_char_cast (str));
169 : : }
170 : 58 : g_free (str);
171 : :
172 : 58 : add_time64 (ret, "trn:date-posted", xaccTransRetDatePosted (trn), TRUE);
173 : :
174 : 58 : add_time64 (ret, "trn:date-entered",
175 : : xaccTransRetDateEntered (trn), TRUE);
176 : :
177 : 58 : str = g_strdup (xaccTransGetDescription (trn));
178 : 58 : if (str)
179 : : {
180 : 58 : xmlNewTextChild (ret, NULL, BAD_CAST "trn:description",
181 : 58 : checked_char_cast (str));
182 : : }
183 : 58 : g_free (str);
184 : :
185 : : /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
186 : 58 : xmlAddChild (ret, qof_instance_slots_to_dom_tree ("trn:slots",
187 : 58 : QOF_INSTANCE (trn)));
188 : :
189 : 58 : add_trans_splits (ret, trn);
190 : :
191 : 58 : return ret;
192 : : }
193 : :
194 : : /***********************************************************************/
195 : :
196 : : struct split_pdata
197 : : {
198 : : Split* split;
199 : : QofBook* book;
200 : : };
201 : :
202 : : static inline gboolean
203 : 469 : set_spl_string (xmlNodePtr node, Split* spl,
204 : : void (*func) (Split* spl, const char* txt))
205 : : {
206 : 469 : gchar* tmp = dom_tree_to_text (node);
207 : 469 : g_return_val_if_fail (tmp, FALSE);
208 : :
209 : 469 : func (spl, tmp);
210 : :
211 : 469 : g_free (tmp);
212 : :
213 : 469 : return TRUE;
214 : : }
215 : :
216 : : static inline gboolean
217 : 3416 : set_spl_gnc_num (xmlNodePtr node, Split* spl,
218 : : void (*func) (Split* spl, gnc_numeric gn))
219 : : {
220 : 3416 : func (spl, dom_tree_to_gnc_numeric (node));
221 : 3416 : return TRUE;
222 : : }
223 : :
224 : : static gboolean
225 : 1708 : spl_id_handler (xmlNodePtr node, gpointer data)
226 : : {
227 : 1708 : struct split_pdata* pdata = static_cast<decltype (pdata)> (data);
228 : 1708 : GncGUID* tmp = dom_tree_to_guid (node);
229 : 1708 : g_return_val_if_fail (tmp, FALSE);
230 : :
231 : 1708 : xaccSplitSetGUID (pdata->split, tmp);
232 : :
233 : 1708 : guid_free (tmp);
234 : 1708 : return TRUE;
235 : : }
236 : :
237 : : static gboolean
238 : 363 : spl_memo_handler (xmlNodePtr node, gpointer data)
239 : : {
240 : 363 : struct split_pdata* pdata = static_cast<decltype (pdata)> (data);
241 : 363 : return set_spl_string (node, pdata->split, xaccSplitSetMemo);
242 : : }
243 : :
244 : : static gboolean
245 : 106 : spl_action_handler (xmlNodePtr node, gpointer data)
246 : : {
247 : 106 : struct split_pdata* pdata = static_cast<decltype (pdata)> (data);
248 : 106 : return set_spl_string (node, pdata->split, xaccSplitSetAction);
249 : : }
250 : :
251 : : static gboolean
252 : 1708 : spl_reconciled_state_handler (xmlNodePtr node, gpointer data)
253 : : {
254 : 1708 : struct split_pdata* pdata = static_cast<decltype (pdata)> (data);
255 : 1708 : gchar* tmp = dom_tree_to_text (node);
256 : 1708 : g_return_val_if_fail (tmp, FALSE);
257 : :
258 : 1708 : xaccSplitSetReconcile (pdata->split, tmp[0]);
259 : :
260 : 1708 : g_free (tmp);
261 : :
262 : 1708 : return TRUE;
263 : : }
264 : :
265 : : static gboolean
266 : 117 : spl_reconcile_date_handler (xmlNodePtr node, gpointer data)
267 : : {
268 : 117 : struct split_pdata* pdata = static_cast<decltype (pdata)> (data);
269 : 117 : time64 time = dom_tree_to_time64 (node);
270 : 117 : if (!dom_tree_valid_time64 (time, node->name)) time = 0;
271 : 117 : xaccSplitSetDateReconciledSecs (pdata->split, time);
272 : 117 : return TRUE;
273 : : }
274 : :
275 : : static gboolean
276 : 1708 : spl_value_handler (xmlNodePtr node, gpointer data)
277 : : {
278 : 1708 : struct split_pdata* pdata = static_cast<decltype (pdata)> (data);
279 : 1708 : return set_spl_gnc_num (node, pdata->split, xaccSplitSetValue);
280 : : }
281 : :
282 : : static gboolean
283 : 1708 : spl_quantity_handler (xmlNodePtr node, gpointer data)
284 : : {
285 : 1708 : struct split_pdata* pdata = static_cast<decltype (pdata)> (data);
286 : 1708 : return set_spl_gnc_num (node, pdata->split, xaccSplitSetAmount);
287 : : }
288 : :
289 : : gboolean gnc_transaction_xml_v2_testing = FALSE;
290 : :
291 : : static gboolean
292 : 1708 : spl_account_handler (xmlNodePtr node, gpointer data)
293 : : {
294 : 1708 : struct split_pdata* pdata = static_cast<decltype (pdata)> (data);
295 : 1708 : GncGUID* id = dom_tree_to_guid (node);
296 : : Account* account;
297 : :
298 : 1708 : g_return_val_if_fail (id, FALSE);
299 : :
300 : 1708 : account = xaccAccountLookup (id, pdata->book);
301 : 1708 : if (!account && gnc_transaction_xml_v2_testing &&
302 : 0 : !guid_equal (id, guid_null ()))
303 : : {
304 : 0 : account = xaccMallocAccount (pdata->book);
305 : 0 : xaccAccountSetGUID (account, id);
306 : 0 : xaccAccountSetCommoditySCU (account,
307 : 0 : xaccSplitGetAmount (pdata->split).denom);
308 : : }
309 : :
310 : 1708 : xaccAccountInsertSplit (account, pdata->split);
311 : :
312 : 1708 : guid_free (id);
313 : :
314 : 1708 : return TRUE;
315 : : }
316 : :
317 : : static gboolean
318 : 5 : spl_lot_handler (xmlNodePtr node, gpointer data)
319 : : {
320 : 5 : struct split_pdata* pdata = static_cast<decltype (pdata)> (data);
321 : 5 : GncGUID* id = dom_tree_to_guid (node);
322 : : GNCLot* lot;
323 : :
324 : 5 : g_return_val_if_fail (id, FALSE);
325 : :
326 : 5 : lot = gnc_lot_lookup (id, pdata->book);
327 : 5 : if (!lot && gnc_transaction_xml_v2_testing &&
328 : 0 : !guid_equal (id, guid_null ()))
329 : : {
330 : 0 : lot = gnc_lot_new (pdata->book);
331 : 0 : gnc_lot_set_guid (lot, *id);
332 : : }
333 : :
334 : 5 : gnc_lot_add_split (lot, pdata->split);
335 : :
336 : 5 : guid_free (id);
337 : :
338 : 5 : return TRUE;
339 : : }
340 : :
341 : : static gboolean
342 : 112 : spl_slots_handler (xmlNodePtr node, gpointer data)
343 : : {
344 : 112 : struct split_pdata* pdata = static_cast<decltype (pdata)> (data);
345 : : gboolean successful;
346 : :
347 : 224 : successful = dom_tree_create_instance_slots (node,
348 : 112 : QOF_INSTANCE (pdata->split));
349 : 112 : g_return_val_if_fail (successful, FALSE);
350 : :
351 : 112 : return TRUE;
352 : : }
353 : :
354 : : struct dom_tree_handler spl_dom_handlers[] =
355 : : {
356 : : { "split:id", spl_id_handler, 1, 0 },
357 : : { "split:memo", spl_memo_handler, 0, 0 },
358 : : { "split:action", spl_action_handler, 0, 0 },
359 : : { "split:reconciled-state", spl_reconciled_state_handler, 1, 0 },
360 : : { "split:reconcile-date", spl_reconcile_date_handler, 0, 0 },
361 : : { "split:value", spl_value_handler, 1, 0 },
362 : : { "split:quantity", spl_quantity_handler, 1, 0 },
363 : : { "split:account", spl_account_handler, 1, 0 },
364 : : { "split:lot", spl_lot_handler, 0, 0 },
365 : : { "split:slots", spl_slots_handler, 0, 0 },
366 : : { NULL, NULL, 0, 0 },
367 : : };
368 : :
369 : : static Split*
370 : 1708 : dom_tree_to_split (xmlNodePtr node, QofBook* book)
371 : : {
372 : : struct split_pdata pdata;
373 : : Split* ret;
374 : :
375 : 1708 : g_return_val_if_fail (book, NULL);
376 : :
377 : 1708 : ret = xaccMallocSplit (book);
378 : 1708 : g_return_val_if_fail (ret, NULL);
379 : :
380 : 1708 : pdata.split = ret;
381 : 1708 : pdata.book = book;
382 : :
383 : : /* this isn't going to work in a testing setup */
384 : 1708 : if (dom_tree_generic_parse (node, spl_dom_handlers, &pdata))
385 : : {
386 : 1708 : return ret;
387 : : }
388 : : else
389 : : {
390 : 0 : xaccSplitDestroy (ret);
391 : 0 : return NULL;
392 : : }
393 : : }
394 : :
395 : : /***********************************************************************/
396 : :
397 : : struct trans_pdata
398 : : {
399 : : Transaction* trans;
400 : : QofBook* book;
401 : : };
402 : :
403 : : static inline gboolean
404 : 1174 : set_tran_string (xmlNodePtr node, Transaction* trn,
405 : : void (*func) (Transaction* trn, const char* txt))
406 : : {
407 : : gchar* tmp;
408 : :
409 : 1174 : tmp = dom_tree_to_text (node);
410 : :
411 : 1174 : g_return_val_if_fail (tmp, FALSE);
412 : :
413 : 1174 : func (trn, tmp);
414 : :
415 : 1174 : g_free (tmp);
416 : :
417 : 1174 : return TRUE;
418 : : }
419 : :
420 : : static gboolean
421 : 1646 : set_tran_time64 (xmlNodePtr node, Transaction * trn,
422 : : void (*func) (Transaction *, time64))
423 : : {
424 : 1646 : time64 time = dom_tree_to_time64 (node);
425 : 1646 : if (!dom_tree_valid_time64 (time, node->name)) time = 0;
426 : 1646 : func (trn, time);
427 : 1646 : return TRUE;
428 : : }
429 : :
430 : : static gboolean
431 : 823 : trn_id_handler (xmlNodePtr node, gpointer trans_pdata)
432 : : {
433 : 823 : struct trans_pdata* pdata = static_cast<decltype (pdata)> (trans_pdata);
434 : 823 : Transaction* trn = pdata->trans;
435 : 823 : GncGUID* tmp = dom_tree_to_guid (node);
436 : :
437 : 823 : g_return_val_if_fail (tmp, FALSE);
438 : :
439 : 823 : xaccTransSetGUID ((Transaction*)trn, tmp);
440 : :
441 : 823 : guid_free (tmp);
442 : :
443 : 823 : return TRUE;
444 : : }
445 : :
446 : : static gboolean
447 : 823 : trn_currency_handler (xmlNodePtr node, gpointer trans_pdata)
448 : : {
449 : 823 : struct trans_pdata* pdata = static_cast<decltype (pdata)> (trans_pdata);
450 : 823 : Transaction* trn = pdata->trans;
451 : : gnc_commodity* ref;
452 : :
453 : 823 : ref = dom_tree_to_commodity_ref (node, pdata->book);
454 : 823 : xaccTransSetCurrency (trn, ref);
455 : :
456 : 823 : return TRUE;
457 : : }
458 : :
459 : : static gboolean
460 : 351 : trn_num_handler (xmlNodePtr node, gpointer trans_pdata)
461 : : {
462 : 351 : struct trans_pdata* pdata = static_cast<decltype (pdata)> (trans_pdata);
463 : 351 : Transaction* trn = pdata->trans;
464 : :
465 : 351 : return set_tran_string (node, trn, xaccTransSetNum);
466 : : }
467 : :
468 : : static gboolean
469 : 823 : trn_date_posted_handler (xmlNodePtr node, gpointer trans_pdata)
470 : : {
471 : 823 : struct trans_pdata* pdata = static_cast<decltype (pdata)> (trans_pdata);
472 : 823 : Transaction* trn = pdata->trans;
473 : :
474 : 823 : return set_tran_time64 (node, trn, xaccTransSetDatePostedSecs);
475 : : }
476 : :
477 : : static gboolean
478 : 823 : trn_date_entered_handler (xmlNodePtr node, gpointer trans_pdata)
479 : : {
480 : 823 : struct trans_pdata* pdata = static_cast<decltype (pdata)> (trans_pdata);
481 : 823 : Transaction* trn = pdata->trans;
482 : :
483 : 823 : return set_tran_time64 (node, trn, xaccTransSetDateEnteredSecs);
484 : : }
485 : :
486 : : static gboolean
487 : 823 : trn_description_handler (xmlNodePtr node, gpointer trans_pdata)
488 : : {
489 : 823 : struct trans_pdata* pdata = static_cast<decltype (pdata)> (trans_pdata);
490 : 823 : Transaction* trn = pdata->trans;
491 : :
492 : 823 : return set_tran_string (node, trn, xaccTransSetDescription);
493 : : }
494 : :
495 : : static gboolean
496 : 56 : trn_slots_handler (xmlNodePtr node, gpointer trans_pdata)
497 : : {
498 : 56 : struct trans_pdata* pdata = static_cast<decltype (pdata)> (trans_pdata);
499 : 56 : Transaction* trn = pdata->trans;
500 : : gboolean successful;
501 : :
502 : 56 : successful = dom_tree_create_instance_slots (node, QOF_INSTANCE (trn));
503 : :
504 : 56 : g_return_val_if_fail (successful, FALSE);
505 : :
506 : 56 : return TRUE;
507 : : }
508 : :
509 : : static gboolean
510 : 823 : trn_splits_handler (xmlNodePtr node, gpointer trans_pdata)
511 : : {
512 : 823 : struct trans_pdata* pdata = static_cast<decltype (pdata)> (trans_pdata);
513 : 823 : Transaction* trn = pdata->trans;
514 : : xmlNodePtr mark;
515 : :
516 : 823 : g_return_val_if_fail (node, FALSE);
517 : 823 : g_return_val_if_fail (node->xmlChildrenNode, FALSE);
518 : :
519 : 5062 : for (mark = node->xmlChildrenNode; mark; mark = mark->next)
520 : : {
521 : : Split* spl;
522 : :
523 : 4239 : if (g_strcmp0 ("text", (char*)mark->name) == 0)
524 : 2531 : continue;
525 : :
526 : 1708 : if (g_strcmp0 ("trn:split", (char*)mark->name))
527 : : {
528 : 0 : return FALSE;
529 : : }
530 : :
531 : 1708 : spl = dom_tree_to_split (mark, pdata->book);
532 : :
533 : 1708 : if (spl)
534 : : {
535 : 1708 : xaccTransAppendSplit (trn, spl);
536 : : }
537 : : else
538 : : {
539 : 0 : return FALSE;
540 : : }
541 : : }
542 : 823 : return TRUE;
543 : : }
544 : :
545 : : struct dom_tree_handler trn_dom_handlers[] =
546 : : {
547 : : { "trn:id", trn_id_handler, 1, 0 },
548 : : { "trn:currency", trn_currency_handler, 0, 0},
549 : : { "trn:num", trn_num_handler, 0, 0 },
550 : : { "trn:date-posted", trn_date_posted_handler, 1, 0 },
551 : : { "trn:date-entered", trn_date_entered_handler, 1, 0 },
552 : : { "trn:description", trn_description_handler, 0, 0 },
553 : : { "trn:slots", trn_slots_handler, 0, 0 },
554 : : { "trn:splits", trn_splits_handler, 1, 0 },
555 : : { NULL, NULL, 0, 0 },
556 : : };
557 : :
558 : : static gboolean
559 : 26437 : gnc_transaction_end_handler (gpointer data_for_children,
560 : : GSList* data_from_children, GSList* sibling_data,
561 : : gpointer parent_data, gpointer global_data,
562 : : gpointer* result, const gchar* tag)
563 : : {
564 : 26437 : Transaction* trn = NULL;
565 : 26437 : xmlNodePtr tree = (xmlNodePtr)data_for_children;
566 : 26437 : gxpf_data* gdata = (gxpf_data*)global_data;
567 : :
568 : 26437 : if (parent_data)
569 : : {
570 : 25569 : return TRUE;
571 : : }
572 : :
573 : : /* OK. For some messed up reason this is getting called again with a
574 : : NULL tag. So we ignore those cases */
575 : 868 : if (!tag)
576 : : {
577 : 50 : return TRUE;
578 : : }
579 : :
580 : 818 : g_return_val_if_fail (tree, FALSE);
581 : :
582 : 1636 : trn = dom_tree_to_transaction (tree,
583 : 818 : static_cast<QofBook*> (gdata->bookdata));
584 : 818 : if (trn != NULL)
585 : : {
586 : 818 : gdata->cb (tag, gdata->parsedata, trn);
587 : : }
588 : :
589 : 818 : xmlFreeNode (tree);
590 : :
591 : 818 : return trn != NULL;
592 : : }
593 : :
594 : : Transaction*
595 : 823 : dom_tree_to_transaction (xmlNodePtr node, QofBook* book)
596 : : {
597 : : Transaction* trn;
598 : : gboolean successful;
599 : : struct trans_pdata pdata;
600 : :
601 : 823 : g_return_val_if_fail (node, NULL);
602 : 823 : g_return_val_if_fail (book, NULL);
603 : :
604 : 823 : trn = xaccMallocTransaction (book);
605 : 823 : g_return_val_if_fail (trn, NULL);
606 : 823 : xaccTransBeginEdit (trn);
607 : :
608 : 823 : pdata.trans = trn;
609 : 823 : pdata.book = book;
610 : :
611 : 823 : successful = dom_tree_generic_parse (node, trn_dom_handlers, &pdata);
612 : :
613 : 823 : xaccTransCommitEdit (trn);
614 : :
615 : 823 : if (!successful)
616 : : {
617 : 0 : xmlElemDump (stdout, NULL, node);
618 : 0 : xaccTransBeginEdit (trn);
619 : 0 : xaccTransDestroy (trn);
620 : 0 : xaccTransCommitEdit (trn);
621 : 0 : trn = NULL;
622 : : }
623 : :
624 : 823 : return trn;
625 : : }
626 : :
627 : : sixtp*
628 : 92 : gnc_transaction_sixtp_parser_create (void)
629 : : {
630 : 92 : return sixtp_dom_parser_new (gnc_transaction_end_handler, NULL, NULL);
631 : : }
|