31 #include "gnc-xml-helper.h" 32 #include "sixtp-utils.h" 33 #include "sixtp-dom-parsers.h" 34 #include <kvp-frame.hpp> 36 static QofLogModule log_module = GNC_MOD_IO;
39 dom_tree_to_guid (xmlNodePtr node)
41 if (!node->properties)
46 if (strcmp ((
char*) node->properties->name,
"type") != 0)
48 PERR (
"Unknown attribute for id tag: %s",
49 node->properties->name ?
50 (
char*) node->properties->name :
"(null)");
57 type = (
char*)xmlNodeGetContent (node->properties->xmlAttrPropertyValue);
60 if ((g_strcmp0 (
"guid", type) == 0) || (g_strcmp0 (
"new", type) == 0))
65 guid_str = (
char*)xmlNodeGetContent (node->xmlChildrenNode);
73 PERR (
"Unknown type %s for attribute type for tag %s",
74 type ? type :
"(null)",
75 node->properties->name ?
76 (
char*) node->properties->name :
"(null)");
84 dom_tree_to_integer_kvp_value (xmlNodePtr node)
90 text = dom_tree_to_text (node);
92 if (string_to_gint64 (text, &daint))
94 ret =
new KvpValue {daint};
101 template <
typename T>
103 dom_tree_to_num (xmlNodePtr node, std::function<
bool(
const char*, T*)>string_to_num, T* num_ptr)
105 auto text = dom_tree_to_text (node);
106 auto ret = string_to_num (text, num_ptr);
112 dom_tree_to_integer (xmlNodePtr node, gint64* daint)
114 return dom_tree_to_num<gint64>(node, string_to_gint64, daint);
118 dom_tree_to_guint16 (xmlNodePtr node, guint16* i)
120 return dom_tree_to_num<guint16>(node, string_to_guint16, i);
124 dom_tree_to_guint (xmlNodePtr node, guint* i)
126 return dom_tree_to_num<guint>(node, string_to_guint, i);
130 dom_tree_to_boolean (xmlNodePtr node, gboolean* b)
134 text = dom_tree_to_text (node);
135 if (g_ascii_strncasecmp (text,
"true", 4) == 0)
141 else if (g_ascii_strncasecmp (text,
"false", 5) == 0)
156 dom_tree_to_double_kvp_value (xmlNodePtr node)
160 KvpValue* ret = NULL;
162 text = dom_tree_to_text (node);
164 if (string_to_double (text, &dadoub))
166 ret =
new KvpValue {dadoub};
175 dom_tree_to_numeric_kvp_value (xmlNodePtr node)
177 return new KvpValue {dom_tree_to_gnc_numeric (node)};
181 dom_tree_to_string_kvp_value (xmlNodePtr node)
184 KvpValue* ret = NULL;
186 datext = dom_tree_to_text (node);
189 ret =
new KvpValue {datext};
196 dom_tree_to_guid_kvp_value (xmlNodePtr node)
199 KvpValue* ret = NULL;
201 daguid = dom_tree_to_guid (node);
204 ret =
new KvpValue {daguid};
211 dom_tree_to_time64_kvp_value (xmlNodePtr node)
213 Time64 t{dom_tree_to_time64 (node)};
214 return new KvpValue {t};
218 dom_tree_to_gdate_kvp_value (xmlNodePtr node)
221 KvpValue* ret = NULL;
223 date = dom_tree_to_gdate (node);
227 ret =
new KvpValue {*date};
236 string_to_binary (
const gchar* str,
void** v, guint64* data_len)
242 g_return_val_if_fail (v != NULL, FALSE);
243 g_return_val_if_fail (data_len != NULL, FALSE);
245 str_len = strlen (str);
250 if ((str_len % 2) != 0)
252 *data_len = str_len / 2;
253 data = g_new0 (guchar, *data_len);
255 for (j = 0, i = 0; i < str_len; i += 2, j++)
261 tmpstr[1] = str[i + 1];
264 converted = strtol (tmpstr, NULL, 16);
266 data[j] = (
unsigned char)converted;
274 static KvpValue* dom_tree_to_kvp_value (xmlNodePtr node);
276 KvpFrame* dom_tree_to_kvp_frame (xmlNodePtr node);
279 dom_tree_to_list_kvp_value (xmlNodePtr node)
283 KvpValue* ret = NULL;
285 for (mark = node->xmlChildrenNode; mark; mark = mark->next)
289 if (g_strcmp0 ((
char*)mark->name,
"text") == 0)
292 new_val = dom_tree_to_kvp_value (mark);
295 list = g_list_prepend (list, (gpointer)new_val);
299 list = g_list_reverse (list);
301 ret =
new KvpValue {list};
307 dom_tree_to_frame_kvp_value (xmlNodePtr node)
310 KvpValue* ret = NULL;
312 frame = dom_tree_to_kvp_frame (node);
316 ret =
new KvpValue {frame};
326 KvpValue* (*converter) (xmlNodePtr node);
333 {
"integer", dom_tree_to_integer_kvp_value },
334 {
"double", dom_tree_to_double_kvp_value },
335 {
"numeric", dom_tree_to_numeric_kvp_value },
336 {
"string", dom_tree_to_string_kvp_value },
337 {
"guid", dom_tree_to_guid_kvp_value },
338 {
"timespec", dom_tree_to_time64_kvp_value },
339 {
"gdate", dom_tree_to_gdate_kvp_value },
340 {
"list", dom_tree_to_list_kvp_value },
341 {
"frame", dom_tree_to_frame_kvp_value },
346 dom_tree_to_kvp_value (xmlNodePtr node)
351 KvpValue* ret = NULL;
353 xml_type = xmlGetProp (node, BAD_CAST
"type");
356 type = g_strdup ((
char*) xml_type);
362 for (mark = val_converters; mark->tag; mark++)
364 if (g_strcmp0 (type, mark->tag) == 0)
366 ret = (mark->converter) (node);
381 dom_tree_to_kvp_frame_given (xmlNodePtr node, KvpFrame* frame)
385 g_return_val_if_fail (node, FALSE);
386 g_return_val_if_fail (frame, FALSE);
388 for (mark = node->xmlChildrenNode; mark; mark = mark->next)
390 if (g_strcmp0 ((
char*)mark->name,
"slot") == 0)
394 KvpValue* val = NULL;
396 for (mark2 = mark->xmlChildrenNode; mark2; mark2 = mark2->next)
398 if (g_strcmp0 ((
char*)mark2->name,
"slot:key") == 0)
400 key = dom_tree_to_text (mark2);
402 else if (g_strcmp0 ((
char*)mark2->name,
"slot:value") == 0)
404 val = dom_tree_to_kvp_value (mark2);
418 delete frame->set ({key}, val);
434 dom_tree_to_kvp_frame (xmlNodePtr node)
436 g_return_val_if_fail (node, NULL);
438 auto ret =
new KvpFrame;
440 if (dom_tree_to_kvp_frame_given (node, ret))
448 dom_tree_create_instance_slots (xmlNodePtr node,
QofInstance* inst)
450 KvpFrame* frame = qof_instance_get_slots (inst);
451 return dom_tree_to_kvp_frame_given (node, frame);
455 dom_tree_to_text (xmlNodePtr tree)
469 g_return_val_if_fail (tree, NULL);
472 if (!tree->xmlChildrenNode)
474 DEBUG (
"No children");
475 return g_strdup (
"");
478 temp = (
char*)xmlNodeListGetString (NULL, tree->xmlChildrenNode, TRUE);
481 DEBUG (
"Null string");
485 DEBUG (
"node string [%s]", (temp == NULL ?
"(null)" : temp));
486 result = g_strdup (temp);
492 dom_tree_to_gnc_numeric (xmlNodePtr node)
494 gchar* content = dom_tree_to_text (node);
496 return gnc_numeric_zero ();
500 num = gnc_numeric_zero ();
508 dom_tree_to_time64 (xmlNodePtr node)
522 gboolean seen = FALSE;
525 for (n = node->xmlChildrenNode; n; n = n->next)
529 case XML_COMMENT_NODE:
532 case XML_ELEMENT_NODE:
533 if (g_strcmp0 (
"ts:date", (
char*)n->name) == 0)
541 gchar* content = dom_tree_to_text (n);
554 PERR (
"unexpected sub-node.");
562 PERR (
"no ts:date node found.");
570 dom_tree_to_gdate (xmlNodePtr node)
581 gboolean seen_date = FALSE;
587 for (n = node->xmlChildrenNode; n; n = n->next)
591 case XML_COMMENT_NODE:
594 case XML_ELEMENT_NODE:
595 if (g_strcmp0 (
"gdate", (
char*)n->name) == 0)
603 gchar* content = dom_tree_to_text (n);
604 gint year, month, day;
610 if (sscanf (content,
"%d-%d-%d", &year, &month, &day) != 3)
617 g_date_set_dmy (ret, day, static_cast<GDateMonth> (month),
619 if (!g_date_valid (ret))
621 PWARN (
"invalid date");
628 PERR (
"unexpected sub-node.");
635 PWARN (
"no gdate node found.");
647 dom_tree_to_commodity_ref_no_engine (xmlNodePtr node, QofBook* book)
659 gnc_commodity* c = NULL;
660 gchar* space_str = NULL;
661 gchar* id_str = NULL;
664 if (!node)
return NULL;
665 if (!node->xmlChildrenNode)
return NULL;
667 for (n = node->xmlChildrenNode; n; n = n->next)
671 case XML_COMMENT_NODE:
674 case XML_ELEMENT_NODE:
675 if (g_strcmp0 (
"cmdty:space", (
char*)n->name) == 0)
683 gchar* content = dom_tree_to_text (n);
684 if (!content)
return NULL;
688 else if (g_strcmp0 (
"cmdty:id", (
char*)n->name) == 0)
696 gchar* content = dom_tree_to_text (n);
697 if (!content)
return NULL;
703 PERR (
"unexpected sub-node.");
708 if (! (space_str && id_str))
714 g_strstrip (space_str);
726 dom_tree_to_commodity_ref (xmlNodePtr node, QofBook* book)
728 gnc_commodity* daref;
730 gnc_commodity_table*
table;
732 daref = dom_tree_to_commodity_ref_no_engine (node, book);
736 g_return_val_if_fail (
table != NULL, NULL);
738 ret = gnc_commodity_table_lookup (
table,
744 g_return_val_if_fail (ret != NULL, NULL);
755 for (; handlers->tag != NULL; handlers++)
757 handlers->gotten = 0;
761 static inline gboolean
765 for (; handlers->tag != NULL; handlers++)
767 if (handlers->required && ! handlers->gotten)
769 PERR (
"Not defined and it should be: %s",
770 handlers->tag ? handlers->tag :
"(null)");
778 static inline gboolean
779 gnc_xml_set_data (
const gchar* tag, xmlNodePtr node, gpointer item,
782 for (; handlers->tag != NULL; handlers++)
784 if (g_strcmp0 (tag, handlers->tag) == 0)
786 (handlers->handler) (node, item);
787 handlers->gotten = TRUE;
794 PERR (
"Unhandled tag: %s",
795 tag ? tag :
"(null)");
807 gboolean successful = TRUE;
809 dom_tree_handlers_reset (handlers);
811 for (achild = node->xmlChildrenNode; achild; achild = achild->next)
814 if (g_strcmp0 ((
char*)achild->name,
"text") == 0)
817 if (!gnc_xml_set_data ((
char*)achild->name, achild, data, handlers))
819 PERR (
"gnc_xml_set_data failed");
825 if (!dom_tree_handlers_all_gotten_p (handlers))
827 PERR (
"didn't find all of the expected tags in the input");
835 dom_tree_valid_time64 (
time64 val,
const xmlChar * name)
837 if (val != INT64_MAX)
839 g_warning (
"Invalid timestamp in data file. Look for a '%s' entry " 840 "with a year outside of the valid range: 1400..10000", name);
time64 gnc_iso8601_to_time64_gmt(const gchar *)
The gnc_iso8601_to_time64_gmt() routine converts an ISO-8601 style date/time string to time64...
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
#define DEBUG(format, args...)
Print a debugging message.
gboolean string_to_guid(const gchar *string, GncGUID *guid)
Given a string, replace the given guid with the parsed one unless the given value is null...
GncGUID * guid_new(void)
Allocate and construct a new GUID.
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
Retrieve the namespace for the specified commodity.
#define PERR(format, args...)
Log a serious error.
#define PWARN(format, args...)
Log a warning.
gnc_commodity * gnc_commodity_new(QofBook *book, const char *fullname, const char *name_space, const char *mnemonic, const char *cusip, int fraction)
Create a new commodity.
All type declarations for the whole Gnucash engine.
gnc_numeric gnc_numeric_from_string(const gchar *str)
Read a gnc_numeric from str, skipping any leading whitespace.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
Check for error signal in value.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
The type used to store guids in C.
void gnc_commodity_destroy(gnc_commodity *cm)
Destroy a commodity.