GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Data Structures | Macros | Typedefs | Functions
io-gncxml-v2.h File Reference

api for GnuCash version 2 XML-based file format More...

#include <glib.h>
#include "gnc-engine.h"
#include "gnc-backend-xml.h"
#include "sixtp.h"

Go to the source code of this file.

Data Structures

struct  load_counter
 
struct  sixtp_gdv2
 
struct  GncXmlDataType_t
 
struct  gnc_template_xaction_data
 
struct  conv_type
 

Macros

#define GNC_FILE_BACKEND   "gnc:file:2"
 
#define GNC_FILE_BACKEND_VERS   2
 

Typedefs

typedef struct sixtp_gdv2 sixtp_gdv2
 
typedef void(* countCallbackFn )(sixtp_gdv2 *gd, const char *type)
 

Functions

void run_callback (sixtp_gdv2 *data, const char *type)
 
gboolean qof_session_load_from_xml_file_v2 (FileBackend *, QofBook *, QofBookFileType)
 
gboolean gnc_book_write_to_xml_filehandle_v2 (QofBook *book, FILE *fh)
 
gboolean gnc_book_write_to_xml_file_v2 (QofBook *book, const char *filename, gboolean compress)
 
gboolean gnc_book_write_accounts_to_xml_filehandle_v2 (QofBackend *be, QofBook *book, FILE *fh)
 
gboolean gnc_book_write_accounts_to_xml_file_v2 (QofBackend *be, QofBook *book, const char *filename)
 
QofBookFileType gnc_is_xml_data_file_v2 (const gchar *name, gboolean *with_encoding)
 
gboolean gnc_xml2_write_namespace_decl (FILE *out, const char *name_space)
 
gint gnc_xml2_find_ambiguous (const gchar *filename, GList *encodings, GHashTable **unique, GHashTable **ambiguous, GList **impossible)
 
gboolean gnc_xml2_parse_with_subst (FileBackend *fbe, QofBook *book, GHashTable *subst)
 

Detailed Description

api for GnuCash version 2 XML-based file format

Author
Initial code by James LewisMoss, 2001

Definition in file io-gncxml-v2.h.

Macro Definition Documentation

#define GNC_FILE_BACKEND   "gnc:file:2"

Struct used to pass in a new data type for XML storage. This contains the set of callbacks to read and write XML for new data objects.. New types should register an instance of this object with the engine.

The create_parser() method will create a new sixtp parser for this data type.

The add_item() method takes a local state and a new object of this type and the method implementation should do whatever is necessary to cleanup the object and (maybe) add it into the book stored in the local-state.

The get_count() method returns the number of items of this type.

The write() method writes out all the objects of this particular type in the book and stores the XML in the FILE.

The scrub() method will take a completed, parsed QofBook* and post process the data, allowing you to 'scrub' the data.

The ns() method will output XML namespace information for the selected plug-in object.

Definition at line 99 of file io-gncxml-v2.h.

Function Documentation

gboolean gnc_book_write_accounts_to_xml_filehandle_v2 ( QofBackend be,
QofBook book,
FILE *  fh 
)

write just the commodities and accounts to a file

Definition at line 1369 of file io-gncxml-v2.c.

1370 {
1372  Account *root;
1373  int ncom, nacc;
1374  sixtp_gdv2 *gd;
1375  gboolean success = TRUE;
1376 
1377  if (!out) return FALSE;
1378 
1379  root = gnc_book_get_root_account(book);
1380  nacc = 1 + gnc_account_n_descendants(root);
1381 
1382  table = gnc_commodity_table_get_table(book);
1383  ncom = gnc_commodity_table_get_size(table);
1384 
1385  if (!write_v2_header(out)
1386  || !write_counts(out, "commodity", ncom, "account", nacc, NULL))
1387  return FALSE;
1388 
1389  gd = gnc_sixtp_gdv2_new(book, TRUE, file_rw_feedback, be->percentage);
1390  gd->counter.commodities_total = ncom;
1391  gd->counter.accounts_total = nacc;
1392 
1393  if (!write_commodities(out, book, gd)
1394  || !write_accounts(out, book, gd)
1395  || fprintf(out, "</" GNC_V2_STRING ">\n\n") < 0)
1396  success = FALSE;
1397 
1398  g_free(gd);
1399  return success;
1400 }
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
gint gnc_account_n_descendants(const Account *account)
Definition: Account.c:2698
guint gnc_commodity_table_get_size(const gnc_commodity_table *tbl)
QofBookFileType gnc_is_xml_data_file_v2 ( const gchar *  name,
gboolean *  with_encoding 
)

The is_gncxml_file() routine checks to see if the first few chars of the file look like gnc-xml data.

Definition at line 1712 of file io-gncxml-v2.c.

1713 {
1714  if (is_gzipped_file(name))
1715  {
1716  gzFile file = NULL;
1717  char first_chunk[256];
1718  int num_read;
1719 
1720 #ifdef G_OS_WIN32
1721  {
1722  gchar *conv_name = g_win32_locale_filename_from_utf8(name);
1723  if (!conv_name)
1724  g_warning("Could not convert '%s' to system codepage", name);
1725  else
1726  {
1727  file = gzopen(conv_name, "rb");
1728  g_free(conv_name);
1729  }
1730  }
1731 #else
1732  file = gzopen(name, "r");
1733 #endif
1734  if (file == NULL)
1735  return GNC_BOOK_NOT_OURS;
1736 
1737  num_read = gzread(file, first_chunk, sizeof(first_chunk) - 1);
1738  gzclose(file);
1739 
1740  if (num_read < 1)
1741  return GNC_BOOK_NOT_OURS;
1742 
1743  return gnc_is_our_first_xml_chunk(first_chunk, with_encoding);
1744  }
1745 
1746  return (gnc_is_our_xml_file(name, with_encoding));
1747 }
gint gnc_xml2_find_ambiguous ( const gchar *  filename,
GList *  encodings,
GHashTable **  unique,
GHashTable **  ambiguous,
GList **  impossible 
)

Read a file as plain byte stream to find words that are not completely ASCII. On error, unique, ambiguous and impossible will be filled up to that point, -1 will be returned.

Parameters
filenameName of the file to read.
encodingsList of encodings to check words for, each begin one a GQuark in a pointer.
uniqueLocation used for a hash table for unique solutions, if not NULL. The byte sequence is the key, successful_conversion the value.
ambiguousLocation used for a hash table for ambiguous byte sequences, if not NULL. The byte sequences is the key, a list of successful_conversions the value.
impossibleLocation used for a list for undecodable byte sequences, if not NULL.
Returns
Size of impossible, -1 on error.

Definition at line 1829 of file io-gncxml-v2.c.

1832 {
1833  FILE *file = NULL;
1834  GList *iconv_list = NULL, *conv_list = NULL, *iter;
1835  iconv_item_type *iconv_item = NULL, *ascii = NULL;
1836  const gchar *enc;
1837  GHashTable *processed = NULL;
1838  gint n_impossible = 0;
1839  GError *error = NULL;
1840  gboolean is_compressed;
1841  gboolean clean_return = FALSE;
1842 
1843  is_compressed = is_gzipped_file(filename);
1844  file = try_gz_open(filename, "r", is_compressed, FALSE);
1845  if (file == NULL)
1846  {
1847  PWARN("Unable to open file %s", filename);
1848  goto cleanup_find_ambs;
1849  }
1850 
1851  /* we need ascii */
1852  ascii = g_new(iconv_item_type, 1);
1853  ascii->encoding = g_quark_from_string("ASCII");
1854  ascii->iconv = g_iconv_open("UTF-8", "ASCII");
1855  if (ascii->iconv == (GIConv) - 1)
1856  {
1857  PWARN("Unable to open ASCII ICONV conversion descriptor");
1858  goto cleanup_find_ambs;
1859  }
1860 
1861  /* call iconv_open on encodings */
1862  for (iter = encodings; iter; iter = iter->next)
1863  {
1864  iconv_item = g_new(iconv_item_type, 1);
1865  iconv_item->encoding = GPOINTER_TO_UINT (iter->data);
1866  if (iconv_item->encoding == ascii->encoding)
1867  {
1868  continue;
1869  }
1870 
1871  enc = g_quark_to_string(iconv_item->encoding);
1872  iconv_item->iconv = g_iconv_open("UTF-8", enc);
1873  if (iconv_item->iconv == (GIConv) - 1)
1874  {
1875  PWARN("Unable to open IConv conversion descriptor for '%s'", enc);
1876  goto cleanup_find_ambs;
1877  }
1878  else
1879  {
1880  iconv_list = g_list_prepend(iconv_list, iconv_item);
1881  }
1882  }
1883 
1884  /* prepare data containers */
1885  if (unique)
1886  *unique = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
1887  (GDestroyNotify) conv_free);
1888  if (ambiguous)
1889  *ambiguous = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
1890  (GDestroyNotify) conv_list_free);
1891  if (impossible)
1892  *impossible = NULL;
1893  processed = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
1894 
1895  /* loop through lines */
1896  while (1)
1897  {
1898  gchar line[256], *word, *utf8;
1899  gchar **word_array, **word_cursor;
1900  conv_type *conv = NULL;
1901 
1902  if (!fgets(line, sizeof(line) - 1, file))
1903  {
1904  if (feof(file))
1905  {
1906  break;
1907  }
1908  else
1909  {
1910  goto cleanup_find_ambs;
1911  }
1912  }
1913 
1914  g_strchomp(line);
1915  replace_character_references(line);
1916  word_array = g_strsplit_set(line, "> <", 0);
1917 
1918  /* loop through words */
1919  for (word_cursor = word_array; *word_cursor; word_cursor++)
1920  {
1921  word = *word_cursor;
1922  if (!word)
1923  continue;
1924 
1925  utf8 = g_convert_with_iconv(word, -1, ascii->iconv,
1926  NULL, NULL, &error);
1927  if (utf8)
1928  {
1929  /* pure ascii */
1930  g_free(utf8);
1931  continue;
1932  }
1933  g_error_free(error);
1934  error = NULL;
1935 
1936  if (g_hash_table_lookup_extended(processed, word, NULL, NULL))
1937  {
1938  /* already processed */
1939  continue;
1940  }
1941 
1942  /* loop through encodings */
1943  conv_list = NULL;
1944  for (iter = iconv_list; iter; iter = iter->next)
1945  {
1946  iconv_item = iter->data;
1947  utf8 = g_convert_with_iconv(word, -1, iconv_item->iconv,
1948  NULL, NULL, &error);
1949  if (utf8)
1950  {
1951  conv = g_new(conv_type, 1);
1952  conv->encoding = iconv_item->encoding;
1953  conv->utf8_string = utf8;
1954  conv_list = g_list_prepend(conv_list, conv);
1955  }
1956  else
1957  {
1958  g_error_free(error);
1959  error = NULL;
1960  }
1961  }
1962 
1963  /* no successful conversion */
1964  if (!conv_list)
1965  {
1966  if (impossible)
1967  *impossible = g_list_append(*impossible, g_strdup(word));
1968  n_impossible++;
1969  }
1970 
1971  /* more than one successful conversion */
1972  else if (conv_list->next)
1973  {
1974  if (ambiguous)
1975  {
1976  g_hash_table_insert(*ambiguous, g_strdup(word), conv_list);
1977  }
1978  else
1979  {
1980  conv_list_free(conv_list);
1981  }
1982  }
1983 
1984  /* only one successful conversion */
1985  else
1986  {
1987  if (unique)
1988  {
1989  g_hash_table_insert(*unique, g_strdup(word), conv);
1990  }
1991  else
1992  {
1993  conv_free(conv);
1994  }
1995  g_list_free(conv_list);
1996  }
1997 
1998  g_hash_table_insert(processed, g_strdup(word), NULL);
1999  }
2000  g_strfreev(word_array);
2001  }
2002 
2003  clean_return = TRUE;
2004 
2005 cleanup_find_ambs:
2006 
2007  if (iconv_list)
2008  {
2009  for (iter = iconv_list; iter; iter = iter->next)
2010  {
2011  if (iter->data)
2012  {
2013  g_iconv_close(((iconv_item_type*) iter->data)->iconv);
2014  g_free(iter->data);
2015  }
2016  }
2017  g_list_free(iconv_list);
2018  }
2019  if (processed)
2020  g_hash_table_destroy(processed);
2021  if (ascii)
2022  g_free(ascii);
2023  if (file)
2024  {
2025  fclose(file);
2026  if (is_compressed)
2027  wait_for_gzip(file);
2028  }
2029 
2030  return (clean_return) ? n_impossible : -1;
2031 }
#define PWARN(format, args...)
Definition: qoflog.h:243
gboolean gnc_xml2_parse_with_subst ( FileBackend fbe,
QofBook book,
GHashTable *  subst 
)

Parse a file in push mode, but replace byte sequences in the file given a hash table of substitutions

Parameters
substhash table with keys and values of type gchar*

Definition at line 2171 of file io-gncxml-v2.c.

2172 {
2173  push_data_type *push_data;
2174  gboolean success;
2175 
2176  push_data = g_new(push_data_type, 1);
2177  push_data->filename = fbe->fullpath;
2178  push_data->subst = subst;
2179 
2180  success = qof_session_load_from_xml_file_v2_full(
2181  fbe, book, (sixtp_push_handler) parse_with_subst_push_handler,
2182  push_data, GNC_BOOK_XML2_FILE);
2183 
2184  if (success)
2185  qof_instance_set_dirty (QOF_INSTANCE (book));
2186 
2187  return success;
2188 }
gboolean gnc_xml2_write_namespace_decl ( FILE *  out,
const char *  name_space 
)

Write a name-space declaration for the provided namespace data type within the GNC XML namespace at http://www.gnucash.org/XML.

Definition at line 1278 of file io-gncxml-v2.c.

1279 {
1280  g_return_val_if_fail(name_space, FALSE);
1281  return fprintf(out, "\n xmlns:%s=\"http://www.gnucash.org/XML/%s\"",
1282  name_space, name_space) >= 0;
1283 }
gboolean qof_session_load_from_xml_file_v2 ( FileBackend ,
QofBook ,
QofBookFileType   
)

read in an account group from a file

Definition at line 865 of file io-gncxml-v2.c.

867 {
868  return qof_session_load_from_xml_file_v2_full(fbe, book, NULL, NULL, type);
869 }
void run_callback ( sixtp_gdv2 data,
const char *  type 
)

Call after loading each record

Definition at line 109 of file io-gncxml-v2.c.

110 {
111  if (data->countCallback)
112  {
113  data->countCallback(data, type);
114  }
115 }