# HG changeset patch # User Ka-Hing Cheung # Date 1194671818 0 # Node ID 78f3361f5e620c4096d9e4733a5c21b0cc314301 # Parent 6de09629f09195969817077621aaa05482fa19f3 make our xmlnode preserve prefixes diff -r 6de09629f091 -r 78f3361f5e62 libpurple/xmlnode.c --- 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", node_name, formatting ? NEWLINE_S : ""); + if (prefix) { + g_string_append_printf(text, "%s", prefix, node_name, formatting ? NEWLINE_S : ""); + } else { + g_string_append_printf(text, "%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); } diff -r 6de09629f091 -r 78f3361f5e62 libpurple/xmlnode.h --- 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.