Mercurial > pidgin
diff libpurple/xmlnode.c @ 32819:2c6510167895 default tip
propagate from branch 'im.pidgin.pidgin.2.x.y' (head 3315c5dfbd0ad16511bdcf865e5b07c02d07df24)
to branch 'im.pidgin.pidgin' (head cbd1eda6bcbf0565ae7766396bb8f6f419cb6a9a)
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Sat, 02 Jun 2012 02:30:49 +0000 |
parents | 8d3b5853b017 |
children |
line wrap: on
line diff
--- a/libpurple/xmlnode.c Sat Jun 02 02:30:13 2012 +0000 +++ b/libpurple/xmlnode.c Sat Jun 02 02:30:49 2012 +0000 @@ -78,6 +78,19 @@ node = new_node(name, XMLNODE_TYPE_TAG); xmlnode_insert_child(parent, node); +#if 0 + /* This would give xmlnodes more appropriate namespacing + * when creating them. Otherwise, unless an explicit namespace + * is set, xmlnode_get_namespace() will return NULL, when + * there may be a default namespace. + * + * I'm unconvinced that it's useful, and concerned it may break things. + * + * _insert_child would need the same thing, probably (assuming + * xmlns->node == NULL) + */ + xmlnode_set_namespace(node, xmlnode_get_default_namespace(node)) +#endif return node; } @@ -191,18 +204,6 @@ } void -xmlnode_set_attrib_with_namespace(xmlnode *node, const char *attr, const char *xmlns, const char *value) -{ - xmlnode_set_attrib_full(node, attr, xmlns, NULL, value); -} - -void -xmlnode_set_attrib_with_prefix(xmlnode *node, const char *attr, const char *prefix, const char *value) -{ - xmlnode_set_attrib_full(node, attr, NULL, prefix, value); -} - -void xmlnode_set_attrib_full(xmlnode *node, const char *attr, const char *xmlns, const char *prefix, const char *value) { xmlnode *attrib_node; @@ -261,19 +262,53 @@ void xmlnode_set_namespace(xmlnode *node, const char *xmlns) { + char *tmp; g_return_if_fail(node != NULL); - g_free(node->xmlns); + tmp = node->xmlns; node->xmlns = g_strdup(xmlns); + + if (node->namespace_map) { + g_hash_table_insert(node->namespace_map, + g_strdup(""), g_strdup(xmlns)); + } + + g_free(tmp); } -const char *xmlnode_get_namespace(xmlnode *node) +const char *xmlnode_get_namespace(const xmlnode *node) { g_return_val_if_fail(node != NULL, NULL); return node->xmlns; } +const char *xmlnode_get_default_namespace(const xmlnode *node) +{ + const xmlnode *current_node; + const char *ns = NULL; + + g_return_val_if_fail(node != NULL, NULL); + + current_node = node; + while (current_node) { + /* If this node does *not* have a prefix, node->xmlns is the default + * namespace. Otherwise, it's the prefix namespace. + */ + if (!current_node->prefix && current_node->xmlns) { + return current_node->xmlns; + } else if (current_node->namespace_map) { + ns = g_hash_table_lookup(current_node->namespace_map, ""); + if (ns && *ns) + return ns; + } + + current_node = current_node->parent; + } + + return ns; +} + void xmlnode_set_prefix(xmlnode *node, const char *prefix) { g_return_if_fail(node != NULL); @@ -288,6 +323,53 @@ return node->prefix; } +const char *xmlnode_get_prefix_namespace(const xmlnode *node, const char *prefix) +{ + const xmlnode *current_node; + + g_return_val_if_fail(node != NULL, NULL); + g_return_val_if_fail(prefix != NULL, xmlnode_get_default_namespace(node)); + + current_node = node; + while (current_node) { + if (current_node->prefix && g_str_equal(prefix, current_node->prefix) && + current_node->xmlns) { + return current_node->xmlns; + } else if (current_node->namespace_map) { + const char *ns = g_hash_table_lookup(current_node->namespace_map, prefix); + if (ns && *ns) { + return ns; + } + } + + current_node = current_node->parent; + } + + return NULL; +} + +void xmlnode_strip_prefixes(xmlnode *node) +{ + xmlnode *child; + const char *prefix; + + g_return_if_fail(node != NULL); + + for (child = node->child; child; child = child->next) { + if (child->type == XMLNODE_TYPE_TAG) + xmlnode_strip_prefixes(child); + } + + prefix = xmlnode_get_prefix(node); + if (prefix) { + const char *ns = xmlnode_get_prefix_namespace(node, prefix); + xmlnode_set_namespace(node, ns); + xmlnode_set_prefix(node, NULL); + } else { + xmlnode_set_namespace(node, xmlnode_get_default_namespace(node)); + } +} + xmlnode *xmlnode_get_parent(const xmlnode *child) { g_return_val_if_fail(child != NULL, NULL); @@ -455,12 +537,22 @@ 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 || !purple_strequal(node->xmlns, node->parent->xmlns)) + } else { + /* Figure out if this node has a different default namespace from parent */ + const char *xmlns = NULL; + const char *parent_xmlns = NULL; + if (!prefix) + xmlns = node->xmlns; + + if (!xmlns) + xmlns = xmlnode_get_default_namespace(node); + if (node->parent) + parent_xmlns = xmlnode_get_default_namespace(node->parent); + if (!purple_strequal(xmlns, parent_xmlns)) { - char *xmlns = g_markup_escape_text(node->xmlns, -1); - g_string_append_printf(text, " xmlns='%s'", xmlns); - g_free(xmlns); + char *escaped_xmlns = g_markup_escape_text(xmlns, -1); + g_string_append_printf(text, " xmlns='%s'", escaped_xmlns); + g_free(escaped_xmlns); } } for(c = node->child; c; c = c->next)