#include "obt/xml.h"
#include "obt/paths.h"
+#include <libxml/xinclude.h>
#include <glib.h>
#ifdef HAVE_STDLIB_H
xmlDocPtr doc;
xmlNodePtr root;
gchar *path;
+ gchar *last_error_file;
+ gint last_error_line;
+ gchar *last_error_message;
};
+static void obt_xml_save_last_error(ObtXmlInst* inst);
+
static void destfunc(struct Callback *c)
{
g_free(c->tag);
- g_free(c);
+ g_slice_free(struct Callback, c);
}
ObtXmlInst* obt_xml_instance_new(void)
{
- ObtXmlInst *i = g_new(ObtXmlInst, 1);
+ ObtXmlInst *i = g_slice_new(ObtXmlInst);
i->ref = 1;
i->xdg_paths = obt_paths_new();
i->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
i->doc = NULL;
i->root = NULL;
i->path = NULL;
+ i->last_error_file = NULL;
+ i->last_error_line = -1;
+ i->last_error_message = NULL;
return i;
}
if (i && --i->ref == 0) {
obt_paths_unref(i->xdg_paths);
g_hash_table_destroy(i->callbacks);
- g_free(i);
+ g_free(i->last_error_file);
+ g_free(i->last_error_message);
+ g_slice_free(ObtXmlInst, i);
}
}
return;
}
- c = g_new(struct Callback, 1);
+ c = g_slice_new(struct Callback);
c->tag = g_strdup(tag);
c->func = func;
c->data = data;
g_hash_table_insert(i->callbacks, c->tag, c);
}
+void obt_xml_unregister(ObtXmlInst *i, const gchar *tag)
+{
+ g_hash_table_remove(i->callbacks, tag);
+}
+
static gboolean load_file(ObtXmlInst *i,
const gchar *domain,
const gchar *filename,
g_assert(i->doc == NULL); /* another doc isn't open already? */
+ xmlResetLastError();
+
for (it = paths; !r && it; it = g_slist_next(it)) {
gchar *path;
struct stat s;
with extra nodes in it. */
i->doc = xmlReadFile(path, NULL, (XML_PARSE_NOBLANKS |
XML_PARSE_RECOVER));
+ xmlXIncludeProcessFlags(i->doc, (XML_PARSE_NOBLANKS |
+ XML_PARSE_RECOVER));
if (i->doc) {
i->root = xmlDocGetRootElement(i->doc);
if (!i->root) {
g_free(path);
}
+ obt_xml_save_last_error(i);
+
return r;
}
g_assert(i->doc == NULL); /* another doc isn't open already? */
+ xmlResetLastError();
+
i->doc = xmlParseMemory(data, len);
if (i) {
i->root = xmlDocGetRootElement(i->doc);
else
r = TRUE; /* ok ! */
}
+
+ obt_xml_save_last_error(i);
+
return r;
}
+static void obt_xml_save_last_error(ObtXmlInst* inst)
+{
+ xmlErrorPtr error = xmlGetLastError();
+ if (error) {
+ inst->last_error_file = g_strdup(error->file);
+ inst->last_error_line = error->line;
+ inst->last_error_message = g_strdup(error->message);
+ xmlResetError(error);
+ }
+}
+
+gboolean obt_xml_last_error(ObtXmlInst *inst)
+{
+ return inst->last_error_file &&
+ inst->last_error_line >= 0 &&
+ inst->last_error_message;
+}
+
+gchar* obt_xml_last_error_file(ObtXmlInst *inst)
+{
+ if (!obt_xml_last_error(inst))
+ return NULL;
+ return inst->last_error_file;
+}
+
+gint obt_xml_last_error_line(ObtXmlInst *inst)
+{
+ if (!obt_xml_last_error(inst))
+ return -1;
+ return inst->last_error_line;
+}
+
+gchar* obt_xml_last_error_message(ObtXmlInst *inst)
+{
+ if (!obt_xml_last_error(inst))
+ return NULL;
+ return inst->last_error_message;
+}
+
gboolean obt_xml_save_file(ObtXmlInst *inst,
const gchar *path,
gboolean pretty)
g_assert(i->doc); /* a doc is open? */
while (node) {
- struct Callback *c = g_hash_table_lookup(i->callbacks, node->name);
- if (c) c->func(node, c->data);
+ if (node->name) {
+ struct Callback *c = g_hash_table_lookup(i->callbacks, node->name);
+ if (c) c->func(node, c->data);
+ }
node = node->next;
}
}
obt_xml_tree(i, i->root->children);
}
-gchar *obt_xml_node_string(xmlNodePtr node)
+gchar *obt_xml_node_string_unstripped(xmlNodePtr node)
{
xmlChar *c = xmlNodeGetContent(node);
gchar *s;
- if (c) g_strstrip((char*)c); /* strip leading/trailing whitespace */
s = g_strdup(c ? (gchar*)c : "");
xmlFree(c);
return s;
}
+gchar *obt_xml_node_string(xmlNodePtr node)
+{
+ gchar* result = obt_xml_node_string_unstripped(node);
+ g_strstrip(result); /* strip leading/trailing whitespace */
+ return result;
+}
+
gint obt_xml_node_int(xmlNodePtr node)
{
xmlChar *c = xmlNodeGetContent(node);
return r;
}
-gboolean obt_xml_attr_string(xmlNodePtr node, const gchar *name,
- gchar **value)
+gboolean obt_xml_attr_string_unstripped(xmlNodePtr node, const gchar *name,
+ gchar **value)
{
xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
gboolean r = FALSE;
if (c) {
- g_strstrip((char*)c); /* strip leading/trailing whitespace */
*value = g_strdup((gchar*)c);
r = TRUE;
}
return r;
}
+gboolean obt_xml_attr_string(xmlNodePtr node, const gchar *name,
+ gchar **value)
+{
+ gboolean result = obt_xml_attr_string_unstripped(node, name, value);
+ if (result)
+ g_strstrip(*value); /* strip leading/trailing whitespace */
+ return result;
+}
+
gboolean obt_xml_attr_contains(xmlNodePtr node, const gchar *name,
const gchar *val)
{