[Gnucash-changes] QOF Sync: QSF

Neil Williams codehelp at cvs.gnucash.org
Wed Aug 17 02:56:19 EDT 2005


Log Message:
-----------
QOF Sync: QSF

Tags:
----
gnucash-gnome2-dev

Modified Files:
--------------
    gnucash/src/backend/qsf:
        .cvsignore
        Makefile.am
        pilot-qsf-GnuCashInvoice.xml
        qof-backend-qsf.h
        qsf-backend.c
        qsf-object.xsd.xml
        qsf-xml-map.c
        qsf-xml.c
        qsf-xml.h

Revision Data
-------------
Index: qsf-xml-map.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qsf-xml-map.c,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -Lsrc/backend/qsf/qsf-xml-map.c -Lsrc/backend/qsf/qsf-xml-map.c -u -r1.1.2.5 -r1.1.2.6
--- src/backend/qsf/qsf-xml-map.c
+++ src/backend/qsf/qsf-xml-map.c
@@ -42,10 +42,11 @@
 
 	output_parent = xmlAddChild(parent_tag, xmlNewNode(ns,
 		xmlGetProp(import_node, BAD_CAST QSF_OBJECT_TYPE)));
-	xmlNewProp(output_parent, BAD_CAST QSF_OBJECT_TYPE, xmlGetProp(import_node, BAD_CAST MAP_VALUE_ATTR));
+	xmlNewProp(output_parent, BAD_CAST QSF_OBJECT_TYPE,
+		xmlGetProp(import_node, BAD_CAST MAP_VALUE_ATTR));
 	qsf_time = (time_t*)g_hash_table_lookup(qsf_default_hash, default_name);
 	strftime(date_as_string, QSF_DATE_LENGTH, QSF_XSD_TIME, gmtime(qsf_time));
-	xmlNodeAddContent(output_parent, date_as_string);
+	xmlNodeAddContent(output_parent, BAD_CAST date_as_string);
 }
 
 static void
@@ -57,7 +58,8 @@
 
 	node = xmlAddChild(parent_tag,
 		xmlNewNode(ns, xmlGetProp(import_node, BAD_CAST QSF_OBJECT_TYPE)));
-	xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, xmlGetProp(import_node, BAD_CAST MAP_VALUE_ATTR));
+	xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE,
+		xmlGetProp(import_node, BAD_CAST MAP_VALUE_ATTR));
 	output = (xmlChar *)g_hash_table_lookup(qsf_default_hash, default_name);
 	xmlNodeAddContent(node, output);
 }
@@ -65,16 +67,15 @@
 void
 qsf_map_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *valid)
 {
-	gchar *qof_version;
+	xmlChar *qof_version, *match;
 	GString *buff;
 	xmlNodePtr child_node;
-	xmlChar *match;
 
 	if (qsf_is_element(child, ns, MAP_DEFINITION_TAG)) {
 		qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION);
 		buff = g_string_new(" ");
 		g_string_printf(buff, "%i", QSF_QOF_VERSION);
-		if(xmlStrcmp(qof_version, buff->str) != 0)
+		if(xmlStrcmp(qof_version, BAD_CAST buff->str) != 0)
 		{
 			valid->error_state = ERR_QSF_BAD_QOF_VERSION;
 			return;
@@ -91,7 +92,7 @@
 	}
 	if(qsf_is_element(child, ns, MAP_OBJECT_TAG)) {
 		match = NULL;
-		match = (xmlChar*) g_hash_table_lookup( valid->validation_table,
+		match = BAD_CAST  g_hash_table_lookup( valid->validation_table,
 			xmlGetProp(child, BAD_CAST MAP_TYPE_ATTR));
 		if(match) {
 			valid->map_calculated_count++;
@@ -144,12 +145,13 @@
 	map_root = xmlDocGetRootElement(map_doc);
 	valid.map_calculated_count = 0;
 	valid.valid_object_count = 0;
+	valid.qof_registered_count = 0;
 	valid.error_state = ERR_BACKEND_NO_ERR;
 	map_ns = map_root->ns;
-	iter.ns = map_ns;
-	qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
 	iter.ns = object_root->ns;
 	qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
+	iter.ns = map_ns;
+	qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
 	if (valid.error_state != ERR_BACKEND_NO_ERR) {
 		qof_backend_set_error(params->be, valid.error_state);
 		g_hash_table_destroy(valid.validation_table);
@@ -164,6 +166,63 @@
 		return TRUE;
 	}
 	qof_backend_set_error(params->be, ERR_QSF_WRONG_MAP);
+	/* the object is OK, only the map is wrong. */
+	return TRUE;
+}
+
+gboolean is_qsf_object_with_map(const char *path, char *map_file)
+{
+	xmlDocPtr doc, map_doc;
+	int valid_count;
+	struct qsf_node_iterate iter;
+	xmlNodePtr map_root, object_root;
+	xmlNsPtr map_ns;
+	qsf_validator valid;
+	gchar *map_path;
+
+	map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file);
+	if(path == NULL) {
+		return FALSE;
+	}
+	doc = xmlParseFile(path);
+	if(doc == NULL) {
+		return FALSE;
+	}
+	if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) {
+		return FALSE;
+	}
+	object_root = xmlDocGetRootElement(doc);
+	if(map_path == NULL) {
+		return FALSE;
+	}
+	valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
+	map_doc = xmlParseFile(map_path);
+	if(map_doc == NULL) {
+		return FALSE;
+	}
+	if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, map_doc)) {
+		return FALSE;
+	}
+	map_root = xmlDocGetRootElement(map_doc);
+	valid.map_calculated_count = 0;
+	valid.valid_object_count = 0;
+	valid.error_state = ERR_BACKEND_NO_ERR;
+	map_ns = map_root->ns;
+	iter.ns = map_ns;
+	qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
+	iter.ns = object_root->ns;
+	qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
+	if (valid.error_state != ERR_BACKEND_NO_ERR) {
+		g_hash_table_destroy(valid.validation_table);
+		return FALSE;
+	}
+	valid_count = 0 - g_hash_table_size(valid.validation_table);
+	valid_count += valid.map_calculated_count;
+	valid_count += valid.valid_object_count;
+	g_hash_table_destroy(valid.validation_table);
+	if(valid_count == 0) {
+		return TRUE;
+	}
 	return FALSE;
 }
 
@@ -284,7 +343,7 @@
 			}
 			else
 /*					if(0 != xmlHashAddEntry(params->default_map,
-				xmlGetProp(child_node, BAD_CAST MAP_NAME_ATTR), child_node))*/
+				xmlGetProp(child_node, MAP_NAME_ATTR), child_node))*/
 			{
 				qof_backend_set_error(params->be, ERR_QSF_BAD_MAP);
 				return;
@@ -296,10 +355,8 @@
 void
 qsf_map_top_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
 {
-	gchar *qof_version;
+	xmlChar	*qof_version;
 	GString *buff;
-/*	xmlChar *qsf_enum;
-	xmlNodePtr child_node;*/
 	struct qsf_node_iterate iter;
 
 	if(!params->qsf_define_hash) return;
@@ -308,7 +365,7 @@
 		qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION);
 		buff = g_string_new(" ");
 		g_string_printf(buff, "%i", QSF_QOF_VERSION);
-		if(xmlStrcmp(qof_version, buff->str) != 0) {
+		if(xmlStrcmp(qof_version, BAD_CAST buff->str) != 0) {
 			qof_backend_set_error(params->be, ERR_QSF_BAD_QOF_VERSION);
 			return;
 		}
@@ -317,9 +374,9 @@
 	}
 }
 
-static xmlChar*
+static char*
 qsf_else_set_value(xmlNodePtr parent, GHashTable *default_hash,
-                   xmlChar *content, xmlNsPtr map_ns)
+		char *content, xmlNsPtr map_ns)
 {
 	xmlNodePtr cur_node;
 
@@ -327,7 +384,7 @@
 	for(cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
 	{
 		if(qsf_is_element(cur_node, map_ns, QSF_CONDITIONAL_SET)) {
-			content = xmlNodeGetContent(cur_node);
+			content = (char*)xmlNodeGetContent(cur_node);
 			return content;
 		}
 	}
@@ -349,12 +406,12 @@
 	{
 		if(qsf_is_element(cur_node, params->map_ns, QSF_CONDITIONAL_SET)) 
 		{
-			content = xmlGetProp(cur_node, BAD_CAST QSF_OPTION);
+			content = (char*)xmlGetProp(cur_node, BAD_CAST QSF_OPTION);
 			if(qsf_strings_equal(xmlGetProp(cur_node, BAD_CAST QSF_OPTION), "qsf_lookup_string")) 
 			{
 				lookup_node = (xmlNodePtr) g_hash_table_lookup(default_hash, 
 					xmlNodeGetContent(cur_node));
-				content = xmlGetProp(lookup_node, BAD_CAST MAP_VALUE_ATTR);
+				content = (char*)xmlGetProp(lookup_node, BAD_CAST MAP_VALUE_ATTR);
 				/** \todo FIXME: do the lookup. type is defined by output object. */
 				/* Find by name, get GUID, return GUID as string. */
 				g_message("Lookup %s in the receiving application\n", content );
@@ -364,16 +421,16 @@
 			{
 				lookup_node = (xmlNodePtr) g_hash_table_lookup(default_hash, 
 					xmlNodeGetContent(cur_node));
-				content = xmlGetProp(lookup_node, BAD_CAST "value");
+				content = (char*)xmlGetProp(lookup_node, BAD_CAST "value");
 				return content;
 			}
-			content = xmlGetProp(parent, BAD_CAST "boolean");
+			content = (char*)xmlGetProp(parent, BAD_CAST "boolean");
 			if(!content) {
 				/** \todo Check qsf_parameter_hash arguments */
 				lookup_node = (xmlNodePtr) g_hash_table_lookup(params->qsf_parameter_hash,
 					xmlGetProp(parent->parent, BAD_CAST MAP_TYPE_ATTR));
-				if(lookup_node) { return xmlNodeGetContent(lookup_node); }
-				return xmlNodeGetContent(cur_node);
+				if(lookup_node) { return (char*)xmlNodeGetContent(lookup_node); }
+				return (char*)xmlNodeGetContent(cur_node);
 			}
 		}
 	}
@@ -389,13 +446,13 @@
 	if(qsf_is_element(param_node, params->map_ns, QSF_CONDITIONAL_ELSE)) {
 		if(params->boolean_calculation_done == 0) {
 			output_content = object_data = NULL;
-			output_content = qsf_set_handler(param_node,
-				params->qsf_default_hash, output_content, params);
+			output_content = BAD_CAST qsf_set_handler(param_node,
+				params->qsf_default_hash, (char*)output_content, params);
 			if(output_content == NULL) {
 				output_content = xmlGetProp(param_node, BAD_CAST MAP_TYPE_ATTR);
-				object_data = qsf_else_set_value(param_node, params->qsf_default_hash,
-					output_content, params->map_ns);
-				output_content = xmlGetProp( (xmlNodePtr) g_hash_table_lookup(
+				object_data = BAD_CAST qsf_else_set_value(param_node, params->qsf_default_hash,
+					(char*)output_content, params->map_ns);
+				output_content = BAD_CAST xmlGetProp( (xmlNodePtr) g_hash_table_lookup(
 					params->qsf_default_hash, object_data), BAD_CAST MAP_VALUE_ATTR);
 			}
 			if(object_data != NULL) {
@@ -446,7 +503,7 @@
 			return;
 		}
 		/** Read the object value as a dateTime  */
-		strptime(xmlNodeGetContent(kl), QSF_XSD_TIME, tmp);
+		strptime((char*)xmlNodeGetContent(kl), QSF_XSD_TIME, tmp);
 		if(!tmp) {
 			printf("empty date field in QSF object.\n");
 			return;
@@ -455,12 +512,12 @@
 		output = &tester;
 	}
 	result = regcomp(&reg, "%[a-zA-Z]", REG_EXTENDED|REG_NOSUB);
-	result = regexec(&reg, format,(size_t)0,NULL,0);
-	if(result == REG_NOMATCH) { format = "%F"; }
+	result = regexec(&reg, (char*)format,(size_t)0,NULL,0);
+	if(result == REG_NOMATCH) { format = BAD_CAST "%F"; }
 	regfree(&reg);
 	/** QSF_DATE_LENGTH preset for all internal and QSF_XSD_TIME string formats.
 	 */
-	strftime(qsf_time_now_as_string, QSF_DATE_LENGTH, format, gmtime(output));
+	strftime(qsf_time_now_as_string, QSF_DATE_LENGTH, (char*)format, gmtime(output));
 }
 
 static void
@@ -490,18 +547,19 @@
 		printf("param_node=%s\n", param_node->name);
 		if(params->boolean_calculation_done == 0) {
 		/* set handler */
-		output_content = qsf_set_handler(param_node, params->qsf_default_hash, output_content, params);
+		output_content = BAD_CAST qsf_set_handler(param_node, params->qsf_default_hash,
+				(char*)output_content, params);
 		/* If the 'if' contains a boolean that has a default value */
 		if(output_content == NULL) {
 			if(NULL != xmlGetProp(param_node, BAD_CAST QSF_BOOLEAN_DEFAULT)) {
 			output_content = xmlGetProp( (xmlNodePtr) g_hash_table_lookup(
-				params->qsf_default_hash, xmlGetProp(param_node, BAD_CAST QSF_BOOLEAN_DEFAULT) ),
-					BAD_CAST MAP_VALUE_ATTR);
+				params->qsf_default_hash, xmlGetProp(param_node,
+				BAD_CAST QSF_BOOLEAN_DEFAULT) ), BAD_CAST MAP_VALUE_ATTR);
 			}
 			/* Is the default set to true? */
 			if( 0 == qsf_compare_tag_strings(output_content, QSF_XML_BOOLEAN_TEST)) 
 			{
-				qsf_boolean_set_value(param_node, params, output_content, params->map_ns);
+				qsf_boolean_set_value(param_node, params, (char*)output_content, params->map_ns);
 				export_node = xmlAddChild(params->lister, xmlNewNode(params->qsf_ns,
 					xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE)));
 				xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE,
@@ -614,3 +672,39 @@
 */
 	}
 }
+xmlDocPtr
+qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, qsf_param *params)
+{
+	struct qsf_node_iterate iter;
+	xmlDocPtr output_doc;
+	xmlNode *cur_node;
+	xmlNode *map_root, *output_root, *output_node;
+
+	output_doc = xmlNewDoc(BAD_CAST QSF_XML_VERSION);
+	output_root = xmlDocCopyNode(qsf_root,output_doc,2);
+	xmlSetNs(output_root, params->qsf_ns);
+	output_node = NULL;
+
+	qsf_node_foreach(qsf_root, qsf_object_node_handler, &iter, params);
+	map_root = xmlDocGetRootElement(mapDoc);
+
+	iter.ns = params->map_ns;
+	qsf_node_foreach(map_root, qsf_map_top_node_handler, &iter, params);
+
+//	iter.ns = qsf_ns;
+//	qsf_node_foreach(qsf_root, qsf_map_object_handler, &iter, params);
+	for(cur_node = map_root->children; cur_node != NULL; cur_node = cur_node->next)
+	{
+		params->cur_node = cur_node;
+		params->count = 0;
+		if(qsf_is_element(cur_node, params->map_ns, MAP_OBJECT_TAG))
+		{
+			params->lister = NULL;
+			params->count++;
+			iter.ns = params->map_ns;
+			qsf_node_foreach(cur_node, qsf_map_object_handler, &iter, params);
+		}
+	}
+	params->file_type = OUR_QSF_OBJ;
+	return output_doc;
+}
Index: qsf-object.xsd.xml
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qsf-object.xsd.xml,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -Lsrc/backend/qsf/qsf-object.xsd.xml -Lsrc/backend/qsf/qsf-object.xsd.xml -u -r1.1.2.5 -r1.1.2.6
--- src/backend/qsf/qsf-object.xsd.xml
+++ src/backend/qsf/qsf-object.xsd.xml
@@ -128,7 +128,7 @@
      </xsd:simpleContent>
      </xsd:complexType>
    </xsd:element>
-   <xsd:element name="collect" minOccurs="0" maxOccurs="unbounded">
+   <xsd:element name="collection" minOccurs="0" maxOccurs="unbounded">
    <xsd:complexType>
    <xsd:simpleContent>
      <xsd:extension base="xsd:hexBinary">
@@ -137,6 +137,16 @@
   </xsd:simpleContent>
   </xsd:complexType>
   </xsd:element>
+  <xsd:element name="choice" minOccurs="0" maxOccurs="unbounded">
+  <xsd:complexType>
+  <xsd:simpleContent>
+   <xsd:extension base="xsd:hexBinary">
+     <xsd:attribute name="type" type="xsd:string" use="required"/>
+     <xsd:attribute name="name" type="xsd:string" use="required"/>
+   </xsd:extension>
+  </xsd:simpleContent>
+  </xsd:complexType>
+  </xsd:element>
 </xsd:sequence>
  <xsd:attribute name="type" type="xsd:string" use="required"/>
  <xsd:attribute name="count" type="xsd:positiveInteger" use="optional"/>
Index: qsf-xml.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qsf-xml.h,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -Lsrc/backend/qsf/qsf-xml.h -Lsrc/backend/qsf/qsf-xml.h -u -r1.1.2.5 -r1.1.2.6
--- src/backend/qsf/qsf-xml.h
+++ src/backend/qsf/qsf-xml.h
@@ -525,6 +525,8 @@
 */
 gboolean is_qsf_object_with_map_be(char *map_path, qsf_param *params);
 
+gboolean is_qsf_object_with_map(const char *path, char *map_file);
+
 /**	\brief QOF processing routine.
 
 Called by ::qof_session_load if a map is required.
@@ -608,7 +610,9 @@
 - QOF_TYPE_INT64
 - QOF_TYPE_DOUBLE
 - QOF_TYPE_CHAR
-- QOF_TYPE_KVP (pending.)
+- QOF_TYPE_KVP
+- QOF_TYPE_COLLECT
+- QOF_TYPE_CHOICE
 
 */
 void qsf_param_init(qsf_param *params);
@@ -752,6 +756,26 @@
 QofBackendError 
 qof_session_load_qsf_object(QofSession *first_session, const char *path);
 
+/** \brief Convert between QSF objects
+
+This is the main workhorse of the conversion between QSF objects using
+maps.
+
+ at param mapDoc The map document, parsed by libxml2.
+ at param qsf_root The top node of the QSF object to be converted using the map.
+ at param params The QSF backend parameters.
+
+Each calculation in the map is performed over the child nodes of the 
+object tree. A new xmlDoc is created and this is made available to QOF to
+be loaded into the book.
+
+*/
+xmlDocPtr
+qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, qsf_param *params);
+
+void
+qsf_object_node_handler(xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params);
+
 /** \brief Backend routine to write a file or stdout.
 
 This function is used by ::qof_session_save to write any QofBook to QSF,
Index: pilot-qsf-GnuCashInvoice.xml
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/pilot-qsf-GnuCashInvoice.xml,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -Lsrc/backend/qsf/pilot-qsf-GnuCashInvoice.xml -Lsrc/backend/qsf/pilot-qsf-GnuCashInvoice.xml -u -r1.1.2.3 -r1.1.2.4
--- src/backend/qsf/pilot-qsf-GnuCashInvoice.xml
+++ src/backend/qsf/pilot-qsf-GnuCashInvoice.xml
@@ -5,9 +5,9 @@
 <qsf-map
 xmlns="http://qof.sourceforge.net/">
 <definition qof_version="3">
-  <define e_type="qof-expenses">Pilot-link QOF expenses</define>
-  <define e_type="qof-datebook">Pilot-link QOF datebook</define>
-  <define e_type="qof-address">Pilot-link QOF address</define>
+  <define e_type="pilot_expenses">Pilot-link QOF expenses</define>
+  <define e_type="pilot_datebook">Pilot-link QOF datebook</define>
+  <define e_type="pilot_address">Pilot-link QOF address</define>
   <define e_type="gncInvoice">Invoice</define>
   <define e_type="Trans">Transaction</define>
   <define e_type="gncEntry">Order/Invoice/Bill Entry</define>
Index: qsf-xml.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qsf-xml.c,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -Lsrc/backend/qsf/qsf-xml.c -Lsrc/backend/qsf/qsf-xml.c -u -r1.1.2.5 -r1.1.2.6
--- src/backend/qsf/qsf-xml.c
+++ src/backend/qsf/qsf-xml.c
@@ -26,9 +26,6 @@
 #include <libxml/xmlversion.h>
 #include "qsf-dir.h"
 #include "qsf-xml.h"
-#include "qofbook-p.h"
-#include "gnc-trace.h"
-static short int module = MOD_BACKEND;
 
 void qsf_free_params(qsf_param *params)
 {
@@ -39,7 +36,6 @@
 	}
 	g_slist_free(params->supported_types);
 	xmlFreeDoc(params->output_doc);
-	xmlFreeNs(params->qsf_ns);
 	xmlFreeNs(params->map_ns);
 }
 
@@ -136,8 +132,11 @@
 			object_declaration = xmlGetProp(cur_node, BAD_CAST QSF_OBJECT_TYPE);
 			count = g_hash_table_size(valid->validation_table);
 			g_hash_table_insert(valid->validation_table, object_declaration, xmlNodeGetContent(cur_node));
-			if((g_hash_table_size(valid->validation_table) > count) &&
-				(TRUE == qof_class_is_registered((QofIdTypeConst) object_declaration)))
+			if(g_hash_table_size(valid->validation_table) > count)
+			{
+				valid->valid_object_count++;
+			}
+			if(TRUE == qof_class_is_registered((QofIdTypeConst) object_declaration))
 			{
 				valid->qof_registered_count++;
 			}
@@ -154,28 +153,18 @@
 	gint table_count;
 
 	g_return_val_if_fail((path != NULL),FALSE);
-	ENTER (" ");
 	if(path == NULL) { return FALSE; }
 	doc = xmlParseFile(path);
 	if(doc == NULL)  { return FALSE; }
-	if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) 
-	{
-		return FALSE;
-	}
+	if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { return FALSE; }
 	object_root = xmlDocGetRootElement(doc);
 	valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
 	valid.qof_registered_count = 0;
 	iter.ns = object_root->ns;
 	qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
 	table_count = g_hash_table_size(valid.validation_table);
-	if(table_count == valid.qof_registered_count)
-	{
 		g_hash_table_destroy(valid.validation_table);
-		LEAVE (" table_count=%i\tvalid_count=%i", table_count, valid.qof_registered_count);
-		return TRUE;
-	}
-	g_hash_table_destroy(valid.validation_table);
-	LEAVE (" table_count=%i\tvalid_count=%i", table_count, valid.qof_registered_count);
+	if(table_count == valid.qof_registered_count) { return TRUE; }
 	return FALSE;
 }
 
@@ -188,10 +177,8 @@
 	doc = xmlParseFile(path);
 	if(doc == NULL) { return FALSE; }
 	if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { return FALSE; }
-	ENTER (" implement a way of finding more than one map");
 	/** \todo implement a way of finding more than one map */
-	/** \todo set the map xmlDocPtr in params for later processing. */
-	return TRUE;
+	return is_qsf_object_with_map(path, "pilot-qsf-GnuCashInvoice.xml");
 }
 
 gboolean is_our_qsf_object_be(qsf_param *params)
@@ -204,15 +191,12 @@
 	char *path;
 
 	g_return_val_if_fail((params != NULL),FALSE);
-	ENTER (" ");
 	path = g_strdup(params->filepath);
 	if(path == NULL) {
 		qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
 		return FALSE;
 	}
-	if(params->file_type != QSF_UNDEF) { 
-		return FALSE; 
-	}
+	if(params->file_type != QSF_UNDEF) { return FALSE; }
 	doc = xmlParseFile(path);
 	if(doc == NULL)  {
 		qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
@@ -234,12 +218,10 @@
 	{
 		g_hash_table_destroy(valid.validation_table);
 		qof_backend_set_error(params->be, ERR_BACKEND_NO_ERR);
-		LEAVE (" table_count=%i\tvalid_count=%i", table_count, valid.qof_registered_count);
 		return TRUE;
 	}
 	g_hash_table_destroy(valid.validation_table);
 	qof_backend_set_error(params->be, ERR_QSF_NO_MAP);
-	LEAVE (" table_count=%i\tvalid_count=%i", table_count, valid.qof_registered_count);
 	return FALSE;
 }
 
@@ -270,7 +252,6 @@
 		}
 	}
 	/** \todo implement a way of finding more than one map */
-	/** \todo set the map xmlDocPtr in params for later processing. */
 	return is_qsf_object_with_map_be("pilot-qsf-GnuCashInvoice.xml", params);
 }
 
@@ -292,15 +273,13 @@
 static void
 qsf_parameter_handler(xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params)
 {
-
 	params->param_node = child;
 	g_slist_foreach(params->supported_types, qsf_supported_data_types, params);
 }
 
-
 /* Despite the name, this function handles the QSF object book tag
 AND the object tags. */
-static void
+void
 qsf_object_node_handler(xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params)
 {
 	struct qsf_node_iterate iter;
@@ -316,8 +295,8 @@
 		object_set = g_new(qsf_objects, 1);
 		params->object_set = object_set;
 		object_set->parameters = g_hash_table_new(g_str_hash, g_str_equal);
-		object_set->object_type = g_strdup(xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE));
-		object_count_s = g_strdup(xmlGetProp(child, BAD_CAST QSF_OBJECT_COUNT));
+		object_set->object_type = g_strdup((char*)xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE));
+		object_count_s = g_strdup((char*)xmlGetProp(child, BAD_CAST QSF_OBJECT_COUNT));
 		c = (int)strtol(object_count_s, &tail, 0);
 		g_free(object_count_s);
 		params->qsf_object_list = g_list_prepend(params->qsf_object_list, object_set);
@@ -338,7 +317,7 @@
 	GUID book_guid;
 
 	if(qsf_is_element(child, ns, QSF_BOOK_TAG)) {
-		book_count_s = xmlGetProp(child,BAD_CAST QSF_BOOK_COUNT);
+		book_count_s = (char*)xmlGetProp(child, BAD_CAST QSF_BOOK_COUNT);
 		if(book_count_s) {
 			book_count = (int)strtol(book_count_s, &tail, 0);
 			/* More than one book not currently supported. */
@@ -351,7 +330,7 @@
 		child_node = child_node->next)
 		{
 		if(qsf_is_element(child_node, ns, QSF_BOOK_GUID)) {
-			buffer = g_strdup(xmlNodeGetContent(child_node));
+			buffer = g_strdup((char*)xmlNodeGetContent(child_node));
 			g_return_if_fail(TRUE == string_to_guid(buffer, &book_guid));
 			qof_entity_set_guid((QofEntity*)params->book, &book_guid);
 			g_free(buffer);
Index: qof-backend-qsf.h
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qof-backend-qsf.h,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -Lsrc/backend/qsf/qof-backend-qsf.h -Lsrc/backend/qsf/qof-backend-qsf.h -u -r1.1.2.1 -r1.1.2.2
--- src/backend/qsf/qof-backend-qsf.h
+++ src/backend/qsf/qof-backend-qsf.h
@@ -124,6 +124,7 @@
 #define _QOF_BACKEND_QSF_H
 
 #include "qofbackend.h"
+#include "qof-be-utils.h"
 
 #ifdef __cplusplus
 extern "C"
Index: .cvsignore
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/.cvsignore,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -Lsrc/backend/qsf/.cvsignore -Lsrc/backend/qsf/.cvsignore -u -r1.1.2.1 -r1.1.2.2
--- src/backend/qsf/.cvsignore
+++ src/backend/qsf/.cvsignore
@@ -5,3 +5,5 @@
 *.lo
 *.la
 qsf-dir.h
+.DS_Store
+
Index: Makefile.am
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/Makefile.am,v
retrieving revision 1.1.2.1
retrieving revision 1.1.2.2
diff -Lsrc/backend/qsf/Makefile.am -Lsrc/backend/qsf/Makefile.am -u -r1.1.2.1 -r1.1.2.2
--- src/backend/qsf/Makefile.am
+++ src/backend/qsf/Makefile.am
@@ -15,9 +15,6 @@
 	qsf-xml-map.c \
         qsf-xml.c
 
-noinst_HEADERS = \
-  qsf-xml.h
-
 LIBADD = \
    ${GLIB_LIBS} \
    ${LIBXML2_LIBS}
@@ -30,7 +27,9 @@
 
 EXTRA_DIST = \
 	$(qsfschema_DATA) \
-	qsf-dir.h.in
+	qsf-dir.h.in      \
+	qof-backend-qsf.h \
+	qsf-xml.h
 
 qsf-dir.h: qsf-dir.h.in
 	rm -f $@.tmp
@@ -40,3 +39,4 @@
 
 BUILT_SOURCES = qsf-dir.h
 
+CONFIG_CLEAN_FILES = qsf-dir.h
Index: qsf-backend.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/backend/qsf/Attic/qsf-backend.c,v
retrieving revision 1.1.2.14
retrieving revision 1.1.2.15
diff -Lsrc/backend/qsf/qsf-backend.c -Lsrc/backend/qsf/qsf-backend.c -u -r1.1.2.14 -r1.1.2.15
--- src/backend/qsf/qsf-backend.c
+++ src/backend/qsf/qsf-backend.c
@@ -33,8 +33,6 @@
 #define QSF_TYPE_GLIST "glist"
 #define QSF_TYPE_FRAME "frame"
 
-static short int module = MOD_BACKEND;
-
 struct QSFBackend_s 
 {
 	QofBackend be;
@@ -81,6 +79,7 @@
 	params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_CHAR);
 	params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_KVP);
 	params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_COLLECT);
+	params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_CHOICE);
 	qsf_time_precision = "%j";
 	qsf_time_now_t = time(NULL);
 	qsf_ts = g_new(Timespec, 1);
@@ -157,7 +156,6 @@
 	qsf_session = qof_session_new();
 	qof_session_begin(qsf_session, path, FALSE, FALSE);
 	qof_session_load(qsf_session, NULL);
-	PINFO (" path=%s", path);
 	/* FIXME: This needs to return success and set the open not merge error in file_open */
 	return ERR_QSF_OPEN_NOT_MERGE;
 }
@@ -165,7 +163,7 @@
 QofBackendError 
 qof_session_load_qsf_object(QofSession *first_session, const char *path)
 {
-	DEBUG (" ERR_QSF_NO_MAP");
+	g_message ("%s = ERR_QSF_NO_MAP", path);
 	return ERR_QSF_NO_MAP;
 }
 
@@ -189,26 +187,67 @@
 	params->filepath = g_strdup(path);
 	qof_backend_get_error(be);
 	result = is_our_qsf_object_be(params);
-	if(result == TRUE) {
+	if(result) {
 		params->file_type = OUR_QSF_OBJ;
 		result = load_our_qsf_object(book, path, params);
-		if(FALSE == result) {
-			qof_backend_set_error(be, ERR_FILEIO_PARSE_ERROR);
-		}
+		if(!result) { qof_backend_set_error(be, ERR_FILEIO_PARSE_ERROR); }
 		return;
 	} 
 	else if(is_qsf_object_be(params)) {
-		qsf_be->params->file_type = IS_QSF_OBJ;
-		if(FALSE == load_qsf_object(book, qsf_be->params->filepath, qsf_be->params)) {
-			qof_backend_set_error(be, ERR_FILEIO_PARSE_ERROR);
+		params->file_type = IS_QSF_OBJ;
+		result = load_qsf_object(book, path, params);
+		if(!result) { qof_backend_set_error(be, ERR_FILEIO_PARSE_ERROR); }
+	}
+	if(result == FALSE) {
+		if(is_qsf_map_be(params)) {
+		params->file_type = IS_QSF_MAP;
+		qof_backend_set_error(be, ERR_QSF_MAP_NOT_OBJ);
 		}
 	}
-	else if(is_qsf_map_be(params)) {
-		qsf_be->params->file_type = IS_QSF_MAP;
-		qof_backend_set_error(be, ERR_QSF_MAP_NOT_OBJ);
+}
+
+static void
+ent_ref_cb (QofEntity* ent, gpointer user_data)
+{
+	qsf_param *params;
+	QofEntityReference *ref;
+	void (*reference_setter) (QofEntity*, QofEntity*);
+	QofEntity *reference;
+	QofCollection *coll;
+	QofIdType type;
+
+	params = (qsf_param*)user_data;
+	g_return_if_fail(params);
+	while(params->referenceList)
+	{
+		ref = (QofEntityReference*)params->referenceList->data;
+		if(qof_object_is_choice(ent->e_type)) { type = ref->choice_type; }
+		else { type = ref->type; }
+		coll = qof_book_get_collection(params->book, type);
+		reference = qof_collection_lookup_entity(coll, ref->ref_guid);
+		reference_setter = (void(*)(QofEntity*, QofEntity*))ref->param->param_setfcn;
+		if(reference_setter != NULL)
+		{
+			qof_begin_edit((QofInstance*)ent);
+			qof_begin_edit((QofInstance*)reference);
+			reference_setter(ent, reference);
+			qof_commit_edit((QofInstance*)ent);
+			qof_commit_edit((QofInstance*)reference);
+		}
+		params->referenceList = g_list_next(params->referenceList);
 	}
 }
 
+static void
+insert_ref_cb(QofObject *obj, gpointer user_data)
+{
+	qsf_param *params;
+
+	params = (qsf_param*)user_data;
+	g_return_if_fail(params);
+	qof_object_foreach(obj->e_type, params->book, ent_ref_cb, params);
+}
+
 /*================================================
 	Load QofEntity into QofBook from XML in memory
 ==================================================*/
@@ -224,10 +263,11 @@
 	xmlNsPtr qsf_ns;
 
 	g_return_val_if_fail(params != NULL, FALSE);
-	g_return_val_if_fail(doc != NULL, FALSE);
+	g_return_val_if_fail(params->input_doc != NULL, FALSE);
 	g_return_val_if_fail(params->book != NULL, FALSE);
 	g_return_val_if_fail(params->file_type == OUR_QSF_OBJ, FALSE);
-	qsf_root = xmlDocGetRootElement(doc);
+	qsf_root = xmlDocGetRootElement(params->input_doc);
+	if(!qsf_root) { return FALSE; }
 	qsf_ns = qsf_root->ns;
 	iter.ns = qsf_ns;
 	book = params->book;
@@ -241,9 +281,12 @@
 		inst = (QofInstance*)qof_object_new_instance(params->object_set->object_type, book);
 		g_return_val_if_fail(inst != NULL, FALSE);
 		params->qsf_ent = &inst->entity;
+		qof_begin_edit(inst);
 		g_hash_table_foreach(params->qsf_parameter_hash, qsf_object_commitCB, params);
+		qof_commit_edit(inst);
 		object_list = g_list_next(object_list);
 	}
+	qof_object_foreach_type(insert_ref_cb, params);
 	qof_book_set_data(book, ENTITYREFERENCE, params->referenceList);
 	return TRUE;
 }
@@ -325,59 +368,67 @@
 	switch(kvp_value_get_type(content))
 	{
 		case KVP_TYPE_STRING:
-			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
-			xmlNodeAddContent(node, kvp_value_to_bare_string(content));
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,qof_param->param_name);
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, path);
+			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
+				BAD_CAST qof_param->param_type));
+			xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
 			xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QOF_TYPE_STRING);
 			break;
 		case KVP_TYPE_GUID:
-			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
-			xmlNodeAddContent(node, kvp_value_to_bare_string(content));
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,qof_param->param_name);
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, path);
+			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
+				BAD_CAST qof_param->param_type));
+			xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
 			xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QOF_TYPE_GUID);
 			break;
 		case KVP_TYPE_BINARY:
-			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
-			xmlNodeAddContent(node, kvp_value_to_bare_string(content));
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,qof_param->param_name);
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, path);
+			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
+				BAD_CAST qof_param->param_type));
+			xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
 			xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QSF_TYPE_BINARY);
 			break;
 		case KVP_TYPE_GLIST:
-			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
-			xmlNodeAddContent(node, kvp_value_to_bare_string(content));
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,qof_param->param_name);
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, path);
+			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
+				BAD_CAST qof_param->param_type));
+			xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
 			xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QSF_TYPE_GLIST);
 			break;
 		case KVP_TYPE_FRAME:
-			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
-			xmlNodeAddContent(node, kvp_value_to_bare_string(content));
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,qof_param->param_name);
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, path);
+			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
+				BAD_CAST qof_param->param_type));
+			xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
 			xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QSF_TYPE_FRAME);
 			break;
 		case KVP_TYPE_GINT64:
-			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
-			xmlNodeAddContent(node, kvp_value_to_bare_string(content));
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,qof_param->param_name);
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, path);
+			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
+				BAD_CAST qof_param->param_type));
+			xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
 			xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QOF_TYPE_INT64);
 			break;
 		case KVP_TYPE_DOUBLE:
-			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
-			xmlNodeAddContent(node, kvp_value_to_bare_string(content));
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,qof_param->param_name);
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, path);
+			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
+				BAD_CAST qof_param->param_type));
+			xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
 			xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QOF_TYPE_DOUBLE);
 			break;
 		case KVP_TYPE_NUMERIC:
-			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
-			xmlNodeAddContent(node, kvp_value_to_bare_string(content));
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,qof_param->param_name);
-			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, path);
+			node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
+				BAD_CAST qof_param->param_type));
+			xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
 			xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QOF_TYPE_NUMERIC);
 			break;
 		default:
@@ -396,10 +447,11 @@
 	params = (qsf_param*)user_data;
 	if(!ent || !params) { return; }
 	qof_param = params->qof_param;
-	node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns, qof_param->param_type));
+	node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
+		BAD_CAST qof_param->param_type));
 	guid_to_string_buff(qof_entity_get_guid(ent), qsf_guid);
-	xmlNodeAddContent(node, qsf_guid);
-	xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,qof_param->param_name);
+	xmlNodeAddContent(node, BAD_CAST qsf_guid);
+	xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
 }
 
 /******* reference handling ***********/
@@ -474,8 +526,8 @@
 		ref_name = g_strdup(reference->param->param_name);
 		node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST QOF_TYPE_GUID));
 		guid_to_string_buff(reference->ref_guid, qsf_guid);
-		xmlNodeAddContent(node, qsf_guid);
-		xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,ref_name);
+		xmlNodeAddContent(node, BAD_CAST qsf_guid);
+		xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST ref_name);
 		g_free(ref_name);
 	}
 }
@@ -495,6 +547,7 @@
 	gchar      *string_buffer;
 	GString    *buffer;
 	QofParam   *qof_param;
+	QofEntity  *choice_ent;
 	KvpFrame   *qsf_kvp;
 	QofCollection *qsf_coll;
 	int        param_count;
@@ -506,15 +559,18 @@
 	params = (qsf_param*)data;
 	param_count = ++params->count;
 	ns = params->qsf_ns;
+	qsf_kvp = kvp_frame_new();
 	own_guid = FALSE;
-	object_node = xmlNewChild(params->book_node, params->qsf_ns, BAD_CAST QSF_OBJECT_TAG, NULL);
-	xmlNewProp(object_node, BAD_CAST QSF_OBJECT_TYPE, ent->e_type); 
+	choice_ent = NULL;
+	object_node = xmlNewChild(params->book_node, params->qsf_ns,
+		BAD_CAST QSF_OBJECT_TAG, NULL);
+	xmlNewProp(object_node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST ent->e_type);
 	buffer = g_string_new(" ");
 	g_string_printf(buffer, "%i", param_count);
-	xmlNewProp(object_node, BAD_CAST QSF_OBJECT_COUNT, buffer->str);
+	xmlNewProp(object_node, BAD_CAST QSF_OBJECT_COUNT, BAD_CAST buffer->str);
 	param_list = g_slist_copy(params->qsf_sequence);
 	while(param_list != NULL) {
-		qof_param = param_list->data;
+		qof_param = (QofParam*)param_list->data;
 		g_return_if_fail(qof_param != NULL);
 		if(0 == safe_strcmp(qof_param->param_type, QOF_TYPE_GUID))
 		{
@@ -524,7 +580,7 @@
 				node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST QOF_TYPE_GUID));
 				guid_to_string_buff(cm_guid, cm_sa);
 				string_buffer = g_strdup(cm_sa);
-				xmlNodeAddContent(node, string_buffer);
+				xmlNodeAddContent(node, BAD_CAST string_buffer);
 				xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE , BAD_CAST QOF_PARAM_GUID);
 				own_guid = TRUE;
 			}
@@ -542,6 +598,26 @@
 			params->output_node = object_node;
 			qof_collection_foreach(qsf_coll, qsf_from_coll_cb, params);
 		}
+		if(0 == safe_strcmp(qof_param->param_type, QOF_TYPE_CHOICE))
+		{
+			/** \todo use the reference list here. */
+			/* repeats due to use of reference list for GUID and CHOICE */
+			/* fix to allow COLLECT too */
+			choice_ent = (QofEntity*)qof_param->param_getfcn(ent, qof_param);
+			if(!choice_ent) {
+				param_list = g_slist_next(param_list);
+				continue;
+			}
+			node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST qof_param->param_type));
+			cm_guid = qof_entity_get_guid(choice_ent);
+			guid_to_string_buff(cm_guid, cm_sa);
+			string_buffer = g_strdup(cm_sa);
+			xmlNodeAddContent(node, BAD_CAST string_buffer);
+			xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
+			xmlNewProp(node, BAD_CAST "name", BAD_CAST choice_ent->e_type);
+			param_list = g_slist_next(param_list);
+			continue;
+		}
 		if(0 == safe_strcmp(qof_param->param_type, QOF_TYPE_KVP))
 		{
 			qsf_kvp = kvp_frame_copy(qof_param->param_getfcn(ent,qof_param));
@@ -551,16 +627,15 @@
 		}
 		if((qof_param->param_setfcn != NULL) && (qof_param->param_getfcn != NULL))
 		{
-			supported = g_slist_copy(params->supported_types);
 			for( supported = g_slist_copy(params->supported_types); 
 				supported != NULL; supported = g_slist_next(supported))
 			{
 				if(0 == safe_strcmp((const char*)supported->data, (const char*)qof_param->param_type))
 				{
-					node = xmlAddChild(object_node, xmlNewNode(ns, qof_param->param_type));
+					node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST qof_param->param_type));
 					string_buffer = g_strdup(qof_book_merge_param_as_string(qof_param, ent));
-					xmlNodeAddContent(node, string_buffer);
-					xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE ,qof_param->param_name);
+					xmlNodeAddContent(node, BAD_CAST string_buffer);
+					xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
 				}
 			}
 		}
@@ -579,7 +654,7 @@
 	params = (qsf_param*) data;
 	/* Skip unsupported objects */
 	if((qsf_obj->create == NULL)||(qsf_obj->foreach == NULL)){
-		DEBUG (" qsf_obj QOF support failed %s", qsf_obj->e_type);
+//		g_message (" qsf_obj QOF support failed %s", qsf_obj->e_type);
 		return;
 	}
 	params->qof_obj_type = qsf_obj->e_type;
@@ -618,7 +693,7 @@
 	xmlNewProp(node, BAD_CAST QSF_BOOK_COUNT, BAD_CAST "1");
 	book_guid = qof_book_get_guid(book);
 	guid_to_string_buff(book_guid, buffer);
-	xmlNewChild(params->book_node, params->qsf_ns, BAD_CAST QSF_BOOK_GUID, buffer);
+	xmlNewChild(params->book_node, params->qsf_ns, BAD_CAST QSF_BOOK_GUID, BAD_CAST buffer);
 	params->output_doc = doc;
 	params->book_node = node;
 	qof_object_foreach_type(qsf_foreach_obj_type, params);
@@ -686,24 +761,28 @@
 gboolean
 load_qsf_object(QofBook *book, const char *fullpath, qsf_param *params)
 {
-	xmlNodePtr qsf_root;
-
-	params->input_doc = xmlParseFile(fullpath);
-	if (params->input_doc == NULL) {
+	xmlNodePtr qsf_root, map_root;
+	xmlDocPtr mapDoc, foreign_doc;
+	gchar *map_path, *map_file;
+
+	map_file = g_strdup("pilot-qsf-GnuCashInvoice.xml");
+	foreign_doc = xmlParseFile(fullpath);
+	if (foreign_doc == NULL) {
 		qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
 		return FALSE;
 	}
 	qsf_root = NULL;
-	qsf_root = xmlDocGetRootElement(params->input_doc);
+	qsf_root = xmlDocGetRootElement(foreign_doc);
 	params->qsf_ns = qsf_root->ns;
 	params->book = book;
-	/* Create a QofBook from the QSF document <b>using a QSF map</b>.
-	
-	May seem strange, but I think we can do this by using the map handlers to
-	create the output_doc in memory as OUR_QSF_OBJ, then pass to the same routine!
-	*/
-
-	return FALSE;
+	map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file);
+	if(map_path == NULL) { return FALSE; }
+	mapDoc = xmlParseFile(map_path);
+	map_root = xmlDocGetRootElement(mapDoc);
+	params->map_ns = map_root->ns;
+	params->input_doc = qsf_object_convert(mapDoc, qsf_root, params);
+	qsfdoc_to_qofbook(params->input_doc, params);
+	return TRUE;
 }
 
 gboolean
@@ -795,7 +874,7 @@
 	QofEntityReference *reference;
 	QofEntity          *qsf_ent;
 	QofBook            *targetBook;
-	const char         *qof_type, *parameter_name;
+	const char         *qof_type, *parameter_name, *timechk;
 	QofIdType          obj_type, reference_type;
 	struct tm          qsf_time;
 	time_t             qsf_time_t;
@@ -829,21 +908,26 @@
 	params = (qsf_param*)data;
 	node = (xmlNodePtr)value;
 	parameter_name = (const char*)key;
-	qof_type = node->name;
+	qof_type = (char*)node->name;
 	qsf_ent = params->qsf_ent;
 	targetBook = params->book;
-	obj_type = xmlGetProp(node->parent, BAD_CAST QSF_OBJECT_TYPE);
+	memset (&qsf_time, '\0', sizeof(qsf_time));
+	cm_date.tv_nsec = 0;
+	cm_date.tv_sec = 0;
+	obj_type = (char*)xmlGetProp(node->parent, BAD_CAST QSF_OBJECT_TYPE);
 	if(0 == safe_strcasecmp(obj_type, parameter_name)) { return; }
 	cm_setter = qof_class_get_parameter_setter(obj_type, parameter_name);
 	cm_param = qof_class_get_parameter(obj_type, parameter_name);
 	object_set = params->object_set;
 	if(safe_strcmp(qof_type, QOF_TYPE_STRING) == 0)  { 
 		string_setter = (void(*)(QofEntity*, const char*))cm_setter;
-		if(string_setter != NULL) { string_setter(qsf_ent, xmlNodeGetContent(node)); }
+		if(string_setter != NULL) { string_setter(qsf_ent, (char*)xmlNodeGetContent(node)); }
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_DATE) == 0) { 
 		date_setter = (void(*)(QofEntity*, Timespec))cm_setter;
-		strptime(xmlNodeGetContent(node), QSF_XSD_TIME, &qsf_time);
+		timechk = NULL;
+		timechk = strptime((char*)xmlNodeGetContent(node), QSF_XSD_TIME, &qsf_time);
+		g_return_if_fail(timechk != NULL);
 		qsf_time_t = mktime(&qsf_time);
 		timespecFromTime_t(&cm_date, qsf_time_t);
 		if(date_setter != NULL) { date_setter(qsf_ent, cm_date); }
@@ -851,18 +935,19 @@
 	if((safe_strcmp(qof_type, QOF_TYPE_NUMERIC) == 0)  ||
 	(safe_strcmp(qof_type, QOF_TYPE_DEBCRED) == 0)) { 
 		numeric_setter = (void(*)(QofEntity*, gnc_numeric))cm_setter;
-		string_to_gnc_numeric(xmlNodeGetContent(node), &cm_numeric);
+		string_to_gnc_numeric((char*)xmlNodeGetContent(node), &cm_numeric);
 		if(numeric_setter != NULL) { numeric_setter(qsf_ent, cm_numeric); }
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_GUID) == 0) { 
 		cm_guid = g_new(GUID, 1);
-		if(TRUE != string_to_guid(xmlNodeGetContent(node), cm_guid))
+		if(TRUE != string_to_guid((char*)xmlNodeGetContent(node), cm_guid))
 		{
 			qof_backend_set_error(params->be, ERR_QSF_BAD_OBJ_GUID);
-			LEAVE (" string to guid failed for %s", xmlNodeGetContent(node));
+			g_message (" string to guid failed for %s:%s:%s",
+				xmlNodeGetContent(node), obj_type, qof_type);
 			return;
 		}
-		reference_type = xmlGetProp(node, BAD_CAST QSF_OBJECT_TYPE);
+		reference_type = (char*)xmlGetProp(node, BAD_CAST QSF_OBJECT_TYPE);
 		if(0 == safe_strcmp(QOF_PARAM_GUID, reference_type)) 
 		{
 			qof_entity_set_guid(qsf_ent, cm_guid);
@@ -876,7 +961,7 @@
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_INT32) == 0) { 
 		errno = 0;
-		cm_i32 = (gint32)strtol (xmlNodeGetContent(node), &tail, 0);
+		cm_i32 = (gint32)strtol ((char*)xmlNodeGetContent(node), &tail, 0);
 		if(errno == 0) {
 			i32_setter = (void(*)(QofEntity*, gint32))cm_setter;
 			if(i32_setter != NULL) { i32_setter(qsf_ent, cm_i32); }
@@ -885,7 +970,7 @@
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_INT64) == 0) { 
 		errno = 0;
-		cm_i64 = strtoll(xmlNodeGetContent(node), &tail, 0);
+		cm_i64 = strtoll((char*)xmlNodeGetContent(node), &tail, 0);
 		if(errno == 0) {
 			i64_setter = (void(*)(QofEntity*, gint64))cm_setter;
 			if(i64_setter != NULL) { i64_setter(qsf_ent, cm_i64); }
@@ -894,14 +979,14 @@
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_DOUBLE) == 0) { 
 		errno = 0;
-		cm_double = strtod(xmlNodeGetContent(node), &tail);
+		cm_double = strtod((char*)xmlNodeGetContent(node), &tail);
 		if(errno == 0) {
 			double_setter = (void(*)(QofEntity*, double))cm_setter;
 			if(double_setter != NULL) { double_setter(qsf_ent, cm_double); }
 		}
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_BOOLEAN) == 0){ 
-		if(0 == safe_strcasecmp(xmlNodeGetContent(node), QSF_XML_BOOLEAN_TEST)) {
+		if(0 == safe_strcasecmp((char*)xmlNodeGetContent(node), QSF_XML_BOOLEAN_TEST)) {
 			cm_boolean = TRUE;
 		}
 		else { cm_boolean = FALSE; }
@@ -909,11 +994,11 @@
 		if(boolean_setter != NULL) { boolean_setter(qsf_ent, cm_boolean); }
 	}
 	if(safe_strcmp(qof_type, QOF_TYPE_KVP) == 0) { 
-		cm_type = qsf_to_kvp_helper(xmlGetProp(node, BAD_CAST QSF_OBJECT_VALUE));
+		cm_type = qsf_to_kvp_helper((char*)xmlGetProp(node, BAD_CAST QSF_OBJECT_VALUE));
 		if(!cm_type) { return; }
-		cm_value = string_to_kvp_value(xmlNodeGetContent(node), cm_type);
+		cm_value = string_to_kvp_value((char*)xmlNodeGetContent(node), cm_type);
 		cm_kvp = kvp_frame_copy(cm_param->param_getfcn(qsf_ent, cm_param));
-		cm_kvp = kvp_frame_set_value(cm_kvp, xmlGetProp(node, BAD_CAST QSF_OBJECT_KVP), cm_value);
+		cm_kvp = kvp_frame_set_value(cm_kvp, (char*)xmlGetProp(node, BAD_CAST QSF_OBJECT_KVP), cm_value);
 		kvp_frame_setter = (void(*)(QofEntity*, KvpFrame*))cm_setter;
 		if(kvp_frame_setter != NULL) { kvp_frame_setter(qsf_ent, cm_kvp); }
 	}
@@ -926,10 +1011,10 @@
 		qsf_coll = cm_param->param_getfcn(qsf_ent, cm_param);
 		type = qof_collection_get_type(qsf_coll);
 		cm_guid = g_new(GUID, 1);
-		if(TRUE != string_to_guid(xmlNodeGetContent(node), cm_guid))
+		if(TRUE != string_to_guid((char*)xmlNodeGetContent(node), cm_guid))
 		{
 			qof_backend_set_error(params->be, ERR_QSF_BAD_OBJ_GUID);
-			LEAVE (" string to guid failed for %s", xmlNodeGetContent(node));
+			g_message (" string to guid collect failed for %s", xmlNodeGetContent(node));
 			return;
 		}
 		// create a QofEntityReference with this type and GUID.


More information about the gnucash-changes mailing list