GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-tax-table-xml-v2.c
1 /********************************************************************\
2  * gnc-tax-table-xml-v2.c -- tax table xml i/o implementation *
3  * *
4  * Copyright (C) 2002 Derek Atkins <[email protected]> *
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 [email protected] *
22  * *
23 \********************************************************************/
24 
25 #include "config.h"
26 
27 #include <glib.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "gnc-xml-helper.h"
32 
33 #include "sixtp.h"
34 #include "sixtp-utils.h"
35 #include "sixtp-parsers.h"
36 #include "sixtp-utils.h"
37 #include "sixtp-dom-parsers.h"
38 #include "sixtp-dom-generators.h"
39 
40 #include "gnc-xml.h"
41 #include "io-gncxml-gen.h"
42 #include "io-gncxml-v2.h"
43 
44 #include "gncEntry.h"
45 #include "gncTaxTableP.h"
46 #include "gnc-tax-table-xml-v2.h"
47 
48 #define _GNC_MOD_NAME GNC_ID_TAXTABLE
49 
50 static QofLogModule log_module = GNC_MOD_IO;
51 
52 const gchar *taxtable_version_string = "2.0.0";
53 
54 /* ids */
55 #define gnc_taxtable_string "gnc:GncTaxTable"
56 #define taxtable_guid_string "taxtable:guid"
57 #define taxtable_name_string "taxtable:name"
58 #define taxtable_refcount_string "taxtable:refcount"
59 #define taxtable_invisible_string "taxtable:invisible"
60 #define taxtable_parent_string "taxtable:parent"
61 #define taxtable_child_string "taxtable:child"
62 #define taxtable_entries_string "taxtable:entries"
63 #define taxtable_slots_string "taxtable:slots"
64 
65 #define gnc_taxtableentry_string "gnc:GncTaxTableEntry"
66 #define ttentry_account_string "tte:acct"
67 #define ttentry_type_string "tte:type"
68 #define ttentry_amount_string "tte:amount"
69 
70 /* EFFECTIVE FRIEND FUNCTION */
71 extern KvpFrame *qof_instance_get_slots (const QofInstance*);
72 
73 static void
74 maybe_add_guid (xmlNodePtr ptr, const char *tag, GncTaxTable *table)
75 {
76  if (table)
77  xmlAddChild (ptr, guid_to_dom_tree (tag,
78  qof_instance_get_guid(QOF_INSTANCE(table))));
79 }
80 
81 static xmlNodePtr
82 ttentry_dom_tree_create (GncTaxTableEntry *entry)
83 {
84  xmlNodePtr ret;
85  Account *account;
86  gnc_numeric amount;
87 
88  ret = xmlNewNode(NULL, BAD_CAST gnc_taxtableentry_string);
89 
90  account = gncTaxTableEntryGetAccount (entry);
91  if (account)
92  xmlAddChild(ret, guid_to_dom_tree (ttentry_account_string,
93  qof_instance_get_guid (QOF_INSTANCE(account))));
94 
95  amount = gncTaxTableEntryGetAmount (entry);
96  xmlAddChild (ret, gnc_numeric_to_dom_tree (ttentry_amount_string, &amount));
97 
98  xmlAddChild(ret, text_to_dom_tree (ttentry_type_string,
99  gncAmountTypeToString (
100  gncTaxTableEntryGetType (entry))));
101 
102  return ret;
103 }
104 
105 static xmlNodePtr
106 taxtable_dom_tree_create (GncTaxTable *table)
107 {
108  xmlNodePtr ret, entries;
109  GList *list;
110  KvpFrame *kf;
111 
112  ret = xmlNewNode(NULL, BAD_CAST gnc_taxtable_string);
113  xmlSetProp(ret, BAD_CAST "version", BAD_CAST taxtable_version_string);
114 
115  maybe_add_guid(ret, taxtable_guid_string, table);
116  xmlAddChild(ret, text_to_dom_tree (taxtable_name_string,
117  gncTaxTableGetName (table)));
118 
119  xmlAddChild(ret, int_to_dom_tree (taxtable_refcount_string,
120  gncTaxTableGetRefcount (table)));
121  xmlAddChild(ret, int_to_dom_tree (taxtable_invisible_string,
122  gncTaxTableGetInvisible (table)));
123 
124  /* We should not be our own child */
125  if (gncTaxTableGetChild(table) != table)
126  maybe_add_guid(ret, taxtable_child_string, gncTaxTableGetChild (table));
127 
128  maybe_add_guid(ret, taxtable_parent_string, gncTaxTableGetParent (table));
129 
130  entries = xmlNewChild (ret, NULL, BAD_CAST taxtable_entries_string, NULL);
131  for (list = gncTaxTableGetEntries (table); list; list = list->next)
132  {
133  GncTaxTableEntry *entry = list->data;
134  xmlAddChild(entries, ttentry_dom_tree_create (entry));
135  }
136 
137  kf = qof_instance_get_slots (QOF_INSTANCE(table));
138  if (kf)
139  {
140  xmlNodePtr kvpnode = kvp_frame_to_dom_tree(taxtable_slots_string, kf);
141  if (kvpnode)
142  {
143  xmlAddChild(ret, kvpnode);
144  }
145  }
146 
147  return ret;
148 }
149 
150 /***********************************************************************/
151 
153 {
154  GncTaxTableEntry *ttentry;
155  QofBook *book;
156 };
157 
158 static gboolean
159 ttentry_acct_handler (xmlNodePtr node, gpointer ttentry_pdata)
160 {
161  struct ttentry_pdata *pdata = ttentry_pdata;
162  GncGUID *guid;
163  Account * acc;
164 
165  guid = dom_tree_to_guid (node);
166  g_return_val_if_fail (guid, FALSE);
167  acc = xaccAccountLookup (guid, pdata->book);
168  g_free (guid);
169  g_return_val_if_fail (acc, FALSE);
170 
171  gncTaxTableEntrySetAccount (pdata->ttentry, acc);
172  return TRUE;
173 }
174 
175 static gboolean
176 ttentry_type_handler (xmlNodePtr node, gpointer taxtable_pdata)
177 {
178  struct ttentry_pdata *pdata = taxtable_pdata;
179  GncAmountType type;
180  char *str;
181  gboolean ret;
182 
183  str = dom_tree_to_text (node);
184  g_return_val_if_fail (str, FALSE);
185 
186  ret = gncAmountStringToType (str, &type);
187  g_free (str);
188 
189  if (ret)
190  gncTaxTableEntrySetType (pdata->ttentry, type);
191 
192  return ret;
193 }
194 
195 static gboolean
196 ttentry_amount_handler (xmlNodePtr node, gpointer ttentry_pdata)
197 {
198  struct ttentry_pdata *pdata = ttentry_pdata;
199  gnc_numeric* num = dom_tree_to_gnc_numeric(node);
200  g_return_val_if_fail(num, FALSE);
201 
202  gncTaxTableEntrySetAmount (pdata->ttentry, *num);
203  g_free(num);
204  return TRUE;
205 }
206 
207 static struct dom_tree_handler ttentry_handlers_v2[] =
208 {
209  { ttentry_account_string, ttentry_acct_handler, 0, 0 },
210  { ttentry_type_string, ttentry_type_handler, 1, 0 },
211  { ttentry_amount_string, ttentry_amount_handler, 1, 0 },
212  { NULL, 0, 0, 0 }
213 };
214 
215 static GncTaxTableEntry*
216 dom_tree_to_ttentry (xmlNodePtr node, QofBook *book)
217 {
219  gboolean successful;
220 
221  ttentry_pdata.ttentry = gncTaxTableEntryCreate ();
222  ttentry_pdata.book = book;
223 
224  successful = dom_tree_generic_parse (node, ttentry_handlers_v2,
225  &ttentry_pdata);
226 
227  if (!successful)
228  {
229  PERR ("failed to parse tax table entry tree");
230  gncTaxTableEntryDestroy (ttentry_pdata.ttentry);
231  ttentry_pdata.ttentry = NULL;
232  }
233 
234  return ttentry_pdata.ttentry;
235 }
236 
237 /***********************************************************************/
238 
239 struct taxtable_pdata
240 {
241  GncTaxTable *table;
242  QofBook *book;
243 };
244 
245 static gboolean
246 set_parent_child (xmlNodePtr node, struct taxtable_pdata *pdata,
247  void (*func)(GncTaxTable *, GncTaxTable *))
248 {
249  GncGUID *guid;
250  GncTaxTable *table;
251 
252  guid = dom_tree_to_guid(node);
253  g_return_val_if_fail (guid, FALSE);
254  table = gncTaxTableLookup (pdata->book, guid);
255 
256  /* Ignore pointers to self */
257  if (table == pdata->table)
258  {
259  PINFO ("found a self-referential parent/child; ignoring.\n");
260  return TRUE;
261  }
262 
263  if (!table)
264  {
265  table = gncTaxTableCreate (pdata->book);
266  gncTaxTableBeginEdit (table);
267  gncTaxTableSetGUID (table, guid);
268  gncTaxTableCommitEdit (table);
269  }
270  g_free (guid);
271  g_return_val_if_fail (table, FALSE);
272  func (pdata->table, table);
273 
274  return TRUE;
275 }
276 
277 static gboolean
278 taxtable_guid_handler (xmlNodePtr node, gpointer taxtable_pdata)
279 {
280  struct taxtable_pdata *pdata = taxtable_pdata;
281  GncGUID *guid;
282  GncTaxTable *table;
283 
284  guid = dom_tree_to_guid(node);
285  g_return_val_if_fail (guid, FALSE);
286  table = gncTaxTableLookup (pdata->book, guid);
287  if (table)
288  {
289  gncTaxTableDestroy (pdata->table);
290  pdata->table = table;
291  gncTaxTableBeginEdit (table);
292  }
293  else
294  {
295  gncTaxTableSetGUID(pdata->table, guid);
296  }
297 
298  g_free(guid);
299 
300  return TRUE;
301 }
302 
303 static gboolean
304 taxtable_name_handler (xmlNodePtr node, gpointer taxtable_pdata)
305 {
306  struct taxtable_pdata *pdata = taxtable_pdata;
307  char* txt = dom_tree_to_text(node);
308  g_return_val_if_fail(txt, FALSE);
309 
310  gncTaxTableSetName (pdata->table, txt);
311  g_free(txt);
312  return TRUE;
313 }
314 
315 static gboolean
316 taxtable_refcount_handler (xmlNodePtr node, gpointer taxtable_pdata)
317 {
318  struct taxtable_pdata *pdata = taxtable_pdata;
319  gint64 val;
320 
321  dom_tree_to_integer(node, &val);
322  gncTaxTableSetRefcount (pdata->table, val);
323  return TRUE;
324 }
325 
326 static gboolean
327 taxtable_invisible_handler (xmlNodePtr node, gpointer taxtable_pdata)
328 {
329  struct taxtable_pdata *pdata = taxtable_pdata;
330  gint64 val;
331 
332  dom_tree_to_integer(node, &val);
333  if (val)
334  gncTaxTableMakeInvisible (pdata->table);
335  return TRUE;
336 }
337 
338 static gboolean
339 taxtable_parent_handler (xmlNodePtr node, gpointer taxtable_pdata)
340 {
341  struct taxtable_pdata *pdata = taxtable_pdata;
342  return set_parent_child (node, pdata, gncTaxTableSetParent);
343 }
344 
345 static gboolean
346 taxtable_child_handler (xmlNodePtr node, gpointer taxtable_pdata)
347 {
348  struct taxtable_pdata *pdata = taxtable_pdata;
349  return set_parent_child (node, pdata, gncTaxTableSetChild);
350 }
351 
352 static gboolean
353 taxtable_entries_handler (xmlNodePtr node, gpointer taxtable_pdata)
354 {
355  struct taxtable_pdata *pdata = taxtable_pdata;
356  xmlNodePtr mark;
357 
358  g_return_val_if_fail (node, FALSE);
359  g_return_val_if_fail (node->xmlChildrenNode, FALSE);
360 
361  for (mark = node->xmlChildrenNode; mark; mark = mark->next)
362  {
363  GncTaxTableEntry *entry;
364 
365  if (g_strcmp0 ("text", (char*)mark->name) == 0)
366  continue;
367 
368  if (g_strcmp0 (gnc_taxtableentry_string, (char*)mark->name))
369  return FALSE;
370 
371  entry = dom_tree_to_ttentry (mark, pdata->book);
372 
373  if (entry)
374  gncTaxTableAddEntry (pdata->table, entry);
375  else
376  return FALSE;
377 
378  }
379  return TRUE;
380 }
381 
382 static gboolean
383 taxtable_slots_handler (xmlNodePtr node, gpointer taxtable_pdata)
384 {
385  struct taxtable_pdata *pdata = taxtable_pdata;
386 
387  return dom_tree_to_kvp_frame_given
388  (node, qof_instance_get_slots (QOF_INSTANCE (pdata->table)));
389 }
390 
391 static struct dom_tree_handler taxtable_handlers_v2[] =
392 {
393  { taxtable_guid_string, taxtable_guid_handler, 1, 0 },
394  { taxtable_name_string, taxtable_name_handler, 1, 0 },
395  { taxtable_refcount_string, taxtable_refcount_handler, 1, 0 },
396  { taxtable_invisible_string, taxtable_invisible_handler, 1, 0 },
397  { taxtable_parent_string, taxtable_parent_handler, 0, 0 },
398  { taxtable_child_string, taxtable_child_handler, 0, 0 },
399  { taxtable_entries_string, taxtable_entries_handler, 1, 0 },
400  { taxtable_slots_string, taxtable_slots_handler, 0, 0 },
401  { NULL, 0, 0, 0 }
402 };
403 
404 static GncTaxTable*
405 dom_tree_to_taxtable (xmlNodePtr node, QofBook *book)
406 {
407  struct taxtable_pdata taxtable_pdata;
408  gboolean successful;
409 
410  taxtable_pdata.table = gncTaxTableCreate (book);
411  taxtable_pdata.book = book;
412  gncTaxTableBeginEdit (taxtable_pdata.table);
413 
414  successful = dom_tree_generic_parse (node, taxtable_handlers_v2,
415  &taxtable_pdata);
416 
417  if (successful)
418  gncTaxTableCommitEdit (taxtable_pdata.table);
419  else
420  {
421  PERR ("failed to parse tax table tree");
422  gncTaxTableDestroy (taxtable_pdata.table);
423  taxtable_pdata.table = NULL;
424  }
425 
426  return taxtable_pdata.table;
427 }
428 
429 static gboolean
430 gnc_taxtable_end_handler(gpointer data_for_children,
431  GSList* data_from_children, GSList* sibling_data,
432  gpointer parent_data, gpointer global_data,
433  gpointer *result, const gchar *tag)
434 {
435  GncTaxTable *table;
436  xmlNodePtr tree = (xmlNodePtr)data_for_children;
437  gxpf_data *gdata = (gxpf_data*)global_data;
438  QofBook *book = gdata->bookdata;
439 
440  if (parent_data)
441  {
442  return TRUE;
443  }
444 
445  /* OK. For some messed up reason this is getting called again with a
446  NULL tag. So we ignore those cases */
447  if (!tag)
448  {
449  return TRUE;
450  }
451 
452  g_return_val_if_fail(tree, FALSE);
453 
454  table = dom_tree_to_taxtable (tree, book);
455  if (table != NULL)
456  {
457  gdata->cb(tag, gdata->parsedata, table);
458  }
459 
460  xmlFreeNode(tree);
461 
462  return table != NULL;
463 }
464 
465 static sixtp *
466 taxtable_sixtp_parser_create(void)
467 {
468  return sixtp_dom_parser_new(gnc_taxtable_end_handler, NULL, NULL);
469 }
470 
471 static void
472 do_count (QofInstance * table_p, gpointer count_p)
473 {
474  int *count = count_p;
475  (*count)++;
476 }
477 
478 static int
479 taxtable_get_count (QofBook *book)
480 {
481  int count = 0;
482  qof_object_foreach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
483  return count;
484 }
485 
486 static void
487 xml_add_taxtable (QofInstance * table_p, gpointer out_p)
488 {
489  xmlNodePtr node;
490  GncTaxTable *table = (GncTaxTable *) table_p;
491  FILE *out = out_p;
492 
493  if (ferror(out))
494  return;
495 
496  node = taxtable_dom_tree_create (table);
497  xmlElemDump(out, NULL, node);
498  xmlFreeNode (node);
499  if (ferror(out) || fprintf(out, "\n") < 0)
500  return;
501 }
502 
503 static gboolean
504 taxtable_write (FILE *out, QofBook *book)
505 {
506  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_taxtable, (gpointer) out);
507  return ferror(out) == 0;
508 }
509 
510 
511 static gboolean
512 taxtable_is_grandchild (GncTaxTable *table)
513 {
514  return (gncTaxTableGetParent(gncTaxTableGetParent(table)) != NULL);
515 }
516 
517 static GncTaxTable *
518 taxtable_find_senior (GncTaxTable *table)
519 {
520  GncTaxTable *temp, *parent, *gp = NULL;
521 
522  temp = table;
523  do
524  {
525  /* See if "temp" is a grandchild */
526  parent = gncTaxTableGetParent(temp);
527  if (!parent)
528  break;
529  gp = gncTaxTableGetParent(parent);
530  if (!gp)
531  break;
532 
533  /* Yep, this is a grandchild. Move up one generation and try again */
534  temp = parent;
535  }
536  while (TRUE);
537 
538  /* Ok, at this point temp points to the most senior child and parent
539  * should point to the top taxtable (and gp should be NULL). If
540  * parent is NULL then we are the most senior child (and have no
541  * children), so do nothing. If temp == table then there is no
542  * grandparent, so do nothing.
543  *
544  * Do something if parent != NULL && temp != table
545  */
546  g_assert (gp == NULL);
547 
548  /* return the most senior table */
549  return temp;
550 }
551 
552 /* build a list of tax tables that are grandchildren or bogus (empty entry list). */
553 static void
554 taxtable_scrub_cb (QofInstance * table_p, gpointer list_p)
555 {
556  GncTaxTable *table = GNC_TAXTABLE(table_p);
557  GList **list = list_p;
558 
559  if (taxtable_is_grandchild(table) || gncTaxTableGetEntries(table) == NULL)
560  *list = g_list_prepend(*list, table);
561 }
562 
563 /* for each entry, check the tax tables. If the tax tables are
564  * grandchildren, then fix them to point to the most senior child
565  */
566 static void
567 taxtable_scrub_entries (QofInstance * entry_p, gpointer ht_p)
568 {
569  GHashTable *ht = ht_p;
570  GncEntry *entry = GNC_ENTRY(entry_p);
571  GncTaxTable *table, *new_tt;
572  gint32 count;
573 
574  table = gncEntryGetInvTaxTable(entry);
575  if (table)
576  {
577  if (taxtable_is_grandchild(table))
578  {
579  gchar guidstr[GUID_ENCODING_LENGTH+1];
580  guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(entry)),guidstr);
581  PINFO("Fixing i-taxtable on entry %s\n",guidstr);
582  new_tt = taxtable_find_senior(table);
583  gncEntryBeginEdit(entry);
584  gncEntrySetInvTaxTable(entry, new_tt);
585  gncEntryCommitEdit(entry);
586  table = new_tt;
587  }
588  if (table)
589  {
590  count = GPOINTER_TO_INT(g_hash_table_lookup(ht, table));
591  count++;
592  g_hash_table_insert(ht, table, GINT_TO_POINTER(count));
593  }
594  }
595 
596  table = gncEntryGetBillTaxTable(entry);
597  if (table)
598  {
599  if (taxtable_is_grandchild(table))
600  {
601  gchar guidstr[GUID_ENCODING_LENGTH+1];
602  guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(entry)),guidstr);
603  PINFO("Fixing b-taxtable on entry %s\n",guidstr);
604  new_tt = taxtable_find_senior(table);
605  gncEntryBeginEdit(entry);
606  gncEntrySetBillTaxTable(entry, new_tt);
607  gncEntryCommitEdit(entry);
608  table = new_tt;
609  }
610  if (table)
611  {
612  count = GPOINTER_TO_INT(g_hash_table_lookup(ht, table));
613  count++;
614  g_hash_table_insert(ht, table, GINT_TO_POINTER(count));
615  }
616  }
617 }
618 
619 static void
620 taxtable_scrub_cust (QofInstance * cust_p, gpointer ht_p)
621 {
622  GHashTable *ht = ht_p;
623  GncCustomer *cust = GNC_CUSTOMER(cust_p);
624  GncTaxTable *table;
625  gint32 count;
626 
627  table = gncCustomerGetTaxTable(cust);
628  if (table)
629  {
630  count = GPOINTER_TO_INT(g_hash_table_lookup(ht, table));
631  count++;
632  g_hash_table_insert(ht, table, GINT_TO_POINTER(count));
633  }
634 }
635 
636 static void
637 taxtable_scrub_vendor (QofInstance * vendor_p, gpointer ht_p)
638 {
639  GHashTable *ht = ht_p;
640  GncVendor *vendor = GNC_VENDOR(vendor_p);
641  GncTaxTable *table;
642  gint32 count;
643 
644  table = gncVendorGetTaxTable(vendor);
645  if (table)
646  {
647  count = GPOINTER_TO_INT(g_hash_table_lookup(ht, table));
648  count++;
649  g_hash_table_insert(ht, table, GINT_TO_POINTER(count));
650  }
651 }
652 
653 static void
654 taxtable_reset_refcount (gpointer key, gpointer value, gpointer notused)
655 {
656  GncTaxTable *table = key;
657  gint32 count = GPOINTER_TO_INT(value);
658 
659  if (count != gncTaxTableGetRefcount(table) && !gncTaxTableGetInvisible(table))
660  {
661  gchar guidstr[GUID_ENCODING_LENGTH+1];
662  guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(table)),guidstr);
663  PWARN("Fixing refcount on taxtable %s (%" G_GINT64_FORMAT " -> %d)\n",
664  guidstr,gncTaxTableGetRefcount(table), count);
665  gncTaxTableSetRefcount(table, count);
666  }
667 }
668 
669 static void
670 taxtable_scrub (QofBook *book)
671 {
672  GList *list = NULL;
673  GList *node;
674  GncTaxTable *parent, *table;
675  GHashTable *ht = g_hash_table_new(g_direct_hash, g_direct_equal);
676 
677  qof_object_foreach (GNC_ID_ENTRY, book, taxtable_scrub_entries, ht);
678  qof_object_foreach (GNC_ID_CUSTOMER, book, taxtable_scrub_cust, ht);
679  qof_object_foreach (GNC_ID_VENDOR, book, taxtable_scrub_vendor, ht);
680  qof_object_foreach (GNC_ID_TAXTABLE, book, taxtable_scrub_cb, &list);
681 
682  /* destroy the list of "grandchildren" tax tables */
683  for (node = list; node; node = node->next)
684  {
685  gchar guidstr[GUID_ENCODING_LENGTH+1];
686  table = node->data;
687 
688  guid_to_string_buff(qof_instance_get_guid(QOF_INSTANCE(table)),guidstr);
689  PINFO ("deleting grandchild taxtable: %s\n", guidstr);
690 
691  /* Make sure the parent has no children */
692  parent = gncTaxTableGetParent(table);
693  gncTaxTableSetChild(parent, NULL);
694 
695  /* Destroy this tax table */
696  gncTaxTableBeginEdit(table);
697  gncTaxTableDestroy(table);
698  }
699 
700  /* reset the refcounts as necessary */
701  g_hash_table_foreach(ht, taxtable_reset_refcount, NULL);
702 
703  g_list_free(list);
704  g_hash_table_destroy(ht);
705 }
706 
707 static gboolean
708 taxtable_ns(FILE *out)
709 {
710  g_return_val_if_fail(out, FALSE);
711  return
712  gnc_xml2_write_namespace_decl(out, "taxtable")
713  && gnc_xml2_write_namespace_decl(out, "tte");
714 }
715 
716 void
717 gnc_taxtable_xml_initialize (void)
718 {
719  static GncXmlDataType_t be_data =
720  {
721  GNC_FILE_BACKEND_VERS,
722  gnc_taxtable_string,
723  taxtable_sixtp_parser_create,
724  NULL, /* add_item */
725  taxtable_get_count,
726  taxtable_write,
727  taxtable_scrub,
728  taxtable_ns,
729  };
730 
731  qof_object_register_backend (_GNC_MOD_NAME,
733  &be_data);
734 }
gboolean qof_object_register_backend(QofIdTypeConst type_name, const char *backend_name, gpointer be_data)
Definition: sixtp.h:93
const GncGUID * qof_instance_get_guid(gconstpointer)
#define GNC_FILE_BACKEND
Definition: io-gncxml-v2.h:99
#define PINFO(format, args...)
Definition: qoflog.h:249
gchar * guid_to_string_buff(const GncGUID *guid, gchar *buff)
#define PERR(format, args...)
Definition: qoflog.h:237
Definition: guid.h:65
#define PWARN(format, args...)
Definition: qoflog.h:243
void qof_object_foreach_sorted(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
api for GnuCash version 2 XML-based file format
#define GUID_ENCODING_LENGTH
Definition: guid.h:74
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
gboolean gnc_xml2_write_namespace_decl(FILE *out, const char *name_space)
struct KvpFrameImpl KvpFrame
Definition: kvp_frame.h:76
Business Entry Interface.
GncAmountType
Definition: gncTaxTable.h:93
const gchar * QofLogModule
Definition: qofid.h:89
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
Definition: Account.c:1827