GnuCash 2.4.99
Data Structures | Defines | 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

Defines

#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 *namespace)
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.


Define 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 1298 of file io-gncxml-v2.c.

{
    gnc_commodity_table *table;
    Account *root;
    int ncom, nacc;
    sixtp_gdv2 *gd;
    gboolean success = TRUE;

    if (!out) return FALSE;

    root = gnc_book_get_root_account(book);
    nacc = 1 + gnc_account_n_descendants(root);

    table = gnc_commodity_table_get_table(book);
    ncom = gnc_commodity_table_get_size(table);

    if (!write_v2_header(out)
            || !write_counts(out, "commodity", ncom, "account", nacc, NULL))
        return FALSE;

    gd = gnc_sixtp_gdv2_new(book, TRUE, file_rw_feedback, be->percentage);
    gd->counter.commodities_total = ncom;
    gd->counter.accounts_total = nacc;

    if (!write_commodities(out, book, gd)
            || !write_accounts(out, book, gd)
            || fprintf(out, "</" GNC_V2_STRING ">\n\n") < 0)
        success = FALSE;

    g_free(gd);
    return success;
}
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 1635 of file io-gncxml-v2.c.

{
    if (is_gzipped_file(name))
    {
        gzFile file = NULL;
        char first_chunk[256];
        int num_read;

#ifdef G_OS_WIN32
        {
            gchar *conv_name = g_win32_locale_filename_from_utf8(name);
            if (!conv_name)
                g_warning("Could not convert '%s' to system codepage", name);
            else
            {
                file = gzopen(conv_name, "rb");
                g_free(conv_name);
            }
        }
#else
        file = gzopen(name, "r");
#endif
        if (file == NULL)
            return GNC_BOOK_NOT_OURS;

        num_read = gzread(file, first_chunk, sizeof(first_chunk) - 1);
        gzclose(file);

        if (num_read < 1)
            return GNC_BOOK_NOT_OURS;

        return gnc_is_our_first_xml_chunk(first_chunk, with_encoding);
    }

    return (gnc_is_our_xml_file(name, with_encoding));
}
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 1752 of file io-gncxml-v2.c.

{
    FILE *file = NULL;
    GList *iconv_list = NULL, *conv_list = NULL, *iter;
    iconv_item_type *iconv_item = NULL, *ascii = NULL;
    const gchar *enc;
    GHashTable *processed = NULL;
    gint n_impossible = 0;
    GError *error = NULL;
    gboolean is_compressed;
    gboolean clean_return = FALSE;

    is_compressed = is_gzipped_file(filename);
    file = try_gz_open(filename, "r", is_compressed, FALSE);
    if (file == NULL)
    {
        PWARN("Unable to open file %s", filename);
        goto cleanup_find_ambs;
    }

    /* we need ascii */
    ascii = g_new(iconv_item_type, 1);
    ascii->encoding = g_quark_from_string("ASCII");
    ascii->iconv = g_iconv_open("UTF-8", "ASCII");
    if (ascii->iconv == (GIConv) - 1)
    {
        PWARN("Unable to open ASCII ICONV conversion descriptor");
        goto cleanup_find_ambs;
    }

    /* call iconv_open on encodings */
    for (iter = encodings; iter; iter = iter->next)
    {
        iconv_item = g_new(iconv_item_type, 1);
        iconv_item->encoding = GPOINTER_TO_UINT (iter->data);
        if (iconv_item->encoding == ascii->encoding)
        {
            continue;
        }

        enc = g_quark_to_string(iconv_item->encoding);
        iconv_item->iconv = g_iconv_open("UTF-8", enc);
        if (iconv_item->iconv == (GIConv) - 1)
        {
            PWARN("Unable to open IConv conversion descriptor for '%s'", enc);
            goto cleanup_find_ambs;
        }
        else
        {
            iconv_list = g_list_prepend(iconv_list, iconv_item);
        }
    }

    /* prepare data containers */
    if (unique)
        *unique = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
                                        (GDestroyNotify) conv_free);
    if (ambiguous)
        *ambiguous = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
                                           (GDestroyNotify) conv_list_free);
    if (impossible)
        *impossible = NULL;
    processed = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);

    /* loop through lines */
    while (1)
    {
        gchar line[256], *word, *utf8;
        gchar **word_array, **word_cursor;
        conv_type *conv = NULL;

        if (!fgets(line, sizeof(line) - 1, file))
        {
            if (feof(file))
            {
                break;
            }
            else
            {
                goto cleanup_find_ambs;
            }
        }

        g_strchomp(line);
        replace_character_references(line);
        word_array = g_strsplit_set(line, "> <", 0);

        /* loop through words */
        for (word_cursor = word_array; *word_cursor; word_cursor++)
        {
            word = *word_cursor;
            if (!word)
                continue;

            utf8 = g_convert_with_iconv(word, -1, ascii->iconv,
                                        NULL, NULL, &error);
            if (utf8)
            {
                /* pure ascii */
                g_free(utf8);
                continue;
            }
            g_error_free(error);
            error = NULL;

            if (g_hash_table_lookup_extended(processed, word, NULL, NULL))
            {
                /* already processed */
                continue;
            }

            /* loop through encodings */
            conv_list = NULL;
            for (iter = iconv_list; iter; iter = iter->next)
            {
                iconv_item = iter->data;
                utf8 = g_convert_with_iconv(word, -1, iconv_item->iconv,
                                            NULL, NULL, &error);
                if (utf8)
                {
                    conv = g_new(conv_type, 1);
                    conv->encoding = iconv_item->encoding;
                    conv->utf8_string = utf8;
                    conv_list = g_list_prepend(conv_list, conv);
                }
                else
                {
                    g_error_free(error);
                    error = NULL;
                }
            }

            /* no successful conversion */
            if (!conv_list)
            {
                if (impossible)
                    *impossible = g_list_append(*impossible, g_strdup(word));
                n_impossible++;
            }

            /* more than one successful conversion */
            else if (conv_list->next)
            {
                if (ambiguous)
                {
                    g_hash_table_insert(*ambiguous, g_strdup(word), conv_list);
                }
                else
                {
                    conv_list_free(conv_list);
                }
            }

            /* only one successful conversion */
            else
            {
                if (unique)
                {
                    g_hash_table_insert(*unique, g_strdup(word), conv);
                }
                else
                {
                    conv_free(conv);
                }
                g_list_free(conv_list);
            }

            g_hash_table_insert(processed, g_strdup(word), NULL);
        }
        g_strfreev(word_array);
    }

    clean_return = TRUE;

cleanup_find_ambs:

    if (iconv_list)
    {
        for (iter = iconv_list; iter; iter = iter->next)
        {
            if (iter->data)
            {
                g_iconv_close(((iconv_item_type*) iter->data)->iconv);
                g_free(iter->data);
            }
        }
        g_list_free(iconv_list);
    }
    if (processed)
        g_hash_table_destroy(processed);
    if (ascii)
        g_free(ascii);
    if (file)
    {
        fclose(file);
        if (is_compressed)
            wait_for_gzip(file);
    }

    return (clean_return) ? n_impossible : -1;
}
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 2094 of file io-gncxml-v2.c.

{
    push_data_type *push_data;
    gboolean success;

    push_data = g_new(push_data_type, 1);
    push_data->filename = fbe->fullpath;
    push_data->subst = subst;

    success = qof_session_load_from_xml_file_v2_full(
                  fbe, book, (sixtp_push_handler) parse_with_subst_push_handler,
                  push_data, GNC_BOOK_XML2_FILE);

    if (success)
        qof_book_kvp_changed(book);

    return success;
}
gboolean gnc_xml2_write_namespace_decl ( FILE *  out,
const char *  namespace 
)

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 1208 of file io-gncxml-v2.c.

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

read in an account group from a file

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

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

Call after loading each record

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

{
    if (data->countCallback)
    {
        data->countCallback(data, type);
    }
}
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines