changeset 21285:78f3361f5e62

make our xmlnode preserve prefixes
author Ka-Hing Cheung <khc@hxbc.us>
date Sat, 10 Nov 2007 05:16:58 +0000
parents 6de09629f091
children b2e646507c18
files libpurple/xmlnode.c libpurple/xmlnode.h
diffstat 2 files changed, 114 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/xmlnode.c	Sat Nov 10 04:52:20 2007 +0000
+++ b/libpurple/xmlnode.c	Sat Nov 10 05:16:58 2007 +0000
@@ -217,7 +217,6 @@
 	g_return_if_fail(value != NULL);
 
 	xmlnode_remove_attrib_with_namespace(node, attr, xmlns);
-
 	attrib_node = new_node(attr, XMLNODE_TYPE_ATTRIB);
 
 	attrib_node->data = g_strdup(value);
@@ -226,6 +225,24 @@
 	xmlnode_insert_child(node, attrib_node);
 }
 
+void
+xmlnode_set_attrib_with_prefix(xmlnode *node, const char *attr, const char *prefix, const char *value)
+{
+	xmlnode *attrib_node;
+
+	g_return_if_fail(node != NULL);
+	g_return_if_fail(attr != NULL);
+	g_return_if_fail(value != NULL);
+
+	attrib_node = new_node(attr, XMLNODE_TYPE_ATTRIB);
+
+	attrib_node->data = g_strdup(value);
+	attrib_node->prefix = g_strdup(prefix);
+
+	xmlnode_insert_child(node, attrib_node);
+}
+
+
 const char *
 xmlnode_get_attrib(xmlnode *node, const char *attr)
 {
@@ -276,6 +293,20 @@
 	return node->xmlns;
 }
 
+void xmlnode_set_prefix(xmlnode *node, const char *prefix)
+{
+	g_return_if_fail(node != NULL);
+
+	g_free(node->prefix);
+	node->prefix = g_strdup(prefix);
+}
+
+const char *xmlnode_get_prefix(xmlnode *node)
+{
+	g_return_val_if_fail(node != NULL, NULL);                                   
+	return node->prefix;
+}
+
 void
 xmlnode_free(xmlnode *node)
 {
@@ -394,10 +425,22 @@
 	return unescaped;
 }
 
+static void
+xmlnode_to_str_foreach_append_ns(const char *key, const char *value,
+	GString *buf)
+{
+	if (*key) {
+		g_string_append_printf(buf, " xmlns:%s='%s'", key, value);
+	} else {
+		g_string_append_printf(buf, " xmlns='%s'", value);
+	}
+}
+
 static char *
 xmlnode_to_str_helper(xmlnode *node, int *len, gboolean formatting, int depth)
 {
 	GString *text = g_string_new("");
+	const char *prefix;
 	xmlnode *c;
 	char *node_name, *esc, *esc2, *tab = NULL;
 	gboolean need_end = FALSE, pretty = formatting;
@@ -410,9 +453,18 @@
 	}
 
 	node_name = g_markup_escape_text(node->name, -1);
-	g_string_append_printf(text, "<%s", node_name);
+	prefix = xmlnode_get_prefix(node);
 
-	if (node->xmlns) {
+	if (prefix) {
+		g_string_append_printf(text, "<%s:%s", prefix, node_name);
+	} else {
+		g_string_append_printf(text, "<%s", node_name);
+	}
+
+	if (node->namespace_map) {
+		g_hash_table_foreach(node->namespace_map,
+			(GHFunc)xmlnode_to_str_foreach_append_ns, text);
+	} else if (node->xmlns) {
 		if(!node->parent || !node->parent->xmlns || strcmp(node->xmlns, node->parent->xmlns))
 		{
 			char *xmlns = g_markup_escape_text(node->xmlns, -1);
@@ -423,9 +475,14 @@
 	for(c = node->child; c; c = c->next)
 	{
 		if(c->type == XMLNODE_TYPE_ATTRIB) {
+			const char *aprefix = xmlnode_get_prefix(c);
 			esc = g_markup_escape_text(c->name, -1);
 			esc2 = g_markup_escape_text(c->data, -1);
-			g_string_append_printf(text, " %s='%s'", esc, esc2);
+			if (aprefix) {
+				g_string_append_printf(text, " %s:%s='%s'", aprefix, esc, esc2);
+			} else {
+				g_string_append_printf(text, " %s='%s'", esc, esc2);
+			}
 			g_free(esc);
 			g_free(esc2);
 		} else if(c->type == XMLNODE_TYPE_TAG || c->type == XMLNODE_TYPE_DATA) {
@@ -454,7 +511,11 @@
 
 		if(tab && pretty)
 			text = g_string_append(text, tab);
-		g_string_append_printf(text, "</%s>%s", node_name, formatting ? NEWLINE_S : "");
+		if (prefix) {
+			g_string_append_printf(text, "</%s:%s>%s", prefix, node_name, formatting ? NEWLINE_S : "");
+		} else {
+			g_string_append_printf(text, "</%s>%s", node_name, formatting ? NEWLINE_S : "");
+		}
 	} else {
 		g_string_append_printf(text, "/>%s", formatting ? NEWLINE_S : "");
 	}
@@ -503,7 +564,7 @@
 {
 	struct _xmlnode_parser_data *xpd = user_data;
 	xmlnode *node;
-	int i;
+	int i, j;
 
 	if(!element_name || xpd->error) {
 		return;
@@ -514,8 +575,22 @@
 			node = xmlnode_new((const char *) element_name);
 
 		xmlnode_set_namespace(node, (const char *) xmlns);
+		xmlnode_set_prefix(node, (const char *)prefix);
+
+		if (nb_namespaces != 0) {
+			node->namespace_map = g_hash_table_new_full(
+				g_str_hash, g_str_equal, g_free, g_free);
+
+			for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
+				const char *key = (const char *)namespaces[j];
+				const char *val = (const char *)namespaces[j + 1];
+				g_hash_table_insert(node->namespace_map,
+					g_strdup(key ? key : ""), g_strdup(val ? val : ""));
+			}
+		}
 
 		for(i=0; i < nb_attributes * 5; i+=5) {
+			const char *prefix = attributes[i + 1];
 			char *txt;
 			int attrib_len = attributes[i+4] - attributes[i+3];
 			char *attrib = g_malloc(attrib_len + 1);
@@ -524,7 +599,11 @@
 			txt = attrib;
 			attrib = purple_unescape_html(txt);
 			g_free(txt);
-			xmlnode_set_attrib(node, (const char*) attributes[i], attrib);
+			if (prefix && *prefix) {
+				xmlnode_set_attrib_with_prefix(node, (const char*) attributes[i], prefix, attrib);
+			} else {
+				xmlnode_set_attrib(node, (const char*) attributes[i], attrib);
+			}
 			g_free(attrib);
 		}
 
--- a/libpurple/xmlnode.h	Sat Nov 10 04:52:20 2007 +0000
+++ b/libpurple/xmlnode.h	Sat Nov 10 05:16:58 2007 +0000
@@ -55,6 +55,8 @@
 	struct _xmlnode *child;		/**< The child node or @c NULL.*/
 	struct _xmlnode *lastchild;	/**< The last child node or @c NULL.*/
 	struct _xmlnode *next;		/**< The next node or @c NULL. */
+	char *prefix;               /**< The namespace prefix if any. */
+	GHashTable *namespace_map;  /**< The namespace map. */
 };
 
 /**
@@ -154,6 +156,16 @@
 void xmlnode_set_attrib(xmlnode *node, const char *attr, const char *value);
 
 /**
+ * Sets a prefixed attribute for a node
+ *
+ * @param node  The node to set an attribute for.
+ * @param attr  The name of the attribute to set
+ * @param xmlns The prefix of the attribute to ste
+ * @param value The value of the attribute
+ */
+void xmlnode_set_attrib_with_prefix(xmlnode *node, const char *attr, const char *prefix, const char *value);
+
+/**
  * Sets a namespaced attribute for a node
  *
  * @param node  The node to set an attribute for.
@@ -218,6 +230,22 @@
 const char *xmlnode_get_namespace(xmlnode *node);
 
 /**
+ * Sets the prefix of a node
+ *
+ * @param node The node to qualify
+ * @param xmlns The prefix of the node
+ */
+void xmlnode_set_prefix(xmlnode *node, const char *prefix);
+
+/**
+ * Returns the prefix of a node
+ *
+ * @param node The node to get the prefix from
+ * @return The prefix of this node
+ */
+const char *xmlnode_get_prefix(xmlnode *node);
+
+/**
  * Returns the node in a string of xml.
  *
  * @param node The starting node to output.