Mercurial > pidgin.yaz
diff libpurple/xmlnode.c @ 32498:114a98da1a5f
xmlnode: Fix some brokeness in xmlnode serialization with prefixed elements.
Basically we were treating node->xmlns as the default namespace, but
that isn't the case with prefexed elements. In our serialization,
I believe we were adding an extraneous xmlns='' to a prefixed element,
which changes the (default) namespace for its children. (It's been
a bit too long with this in my tree, so I've forgotten the exact details)
| author | Paul Aurich <paul@darkrain42.org> |
|---|---|
| date | Sun, 04 Sep 2011 18:52:18 +0000 |
| parents | 67addaf8677f |
| children | 8d3b5853b017 |
line wrap: on
line diff
--- a/libpurple/xmlnode.c Sun Sep 04 18:45:51 2011 +0000 +++ b/libpurple/xmlnode.c Sun Sep 04 18:52:18 2011 +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; } @@ -255,13 +268,34 @@ node->xmlns = g_strdup(xmlns); } -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 char *ns = NULL; + g_return_val_if_fail(node != NULL, NULL); + + /* If this node does *not* have a prefix, node->xmlns is the default + * namespace. Otherwise, it's the prefix namespace. + */ + if (!node->prefix && node->xmlns) { + return node->xmlns; + } else if (node->namespace_map) { + ns = g_hash_table_lookup(node->namespace_map, ""); + } + + /* No default ns found? Walk up the tree looking for one */ + if (!(ns && *ns) && node->parent) + ns = xmlnode_get_default_namespace(node->parent); + + return ns; +} + void xmlnode_set_prefix(xmlnode *node, const char *prefix) { g_return_if_fail(node != NULL); @@ -443,12 +477,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)
