Mercurial > pidgin
comparison libpurple/xmlnode.c @ 32038:8d3b5853b017
xmlnode: Add xmlnode_strip_prefixes
This is largely based on a patch from Thijs (sphynx/xnyhps) Alkemade, with
some modifications by me to try to maintain namespaces of elements
as best as we can.
I also rewrote xmlnode_get_default_namespace not to use recursion.
References #14529
| author | Paul Aurich <paul@darkrain42.org> |
|---|---|
| date | Sun, 04 Sep 2011 21:06:26 +0000 |
| parents | 114a98da1a5f |
| children |
comparison
equal
deleted
inserted
replaced
| 32037:114a98da1a5f | 32038:8d3b5853b017 |
|---|---|
| 260 } | 260 } |
| 261 | 261 |
| 262 | 262 |
| 263 void xmlnode_set_namespace(xmlnode *node, const char *xmlns) | 263 void xmlnode_set_namespace(xmlnode *node, const char *xmlns) |
| 264 { | 264 { |
| 265 char *tmp; | |
| 265 g_return_if_fail(node != NULL); | 266 g_return_if_fail(node != NULL); |
| 266 | 267 |
| 267 g_free(node->xmlns); | 268 tmp = node->xmlns; |
| 268 node->xmlns = g_strdup(xmlns); | 269 node->xmlns = g_strdup(xmlns); |
| 270 | |
| 271 if (node->namespace_map) { | |
| 272 g_hash_table_insert(node->namespace_map, | |
| 273 g_strdup(""), g_strdup(xmlns)); | |
| 274 } | |
| 275 | |
| 276 g_free(tmp); | |
| 269 } | 277 } |
| 270 | 278 |
| 271 const char *xmlnode_get_namespace(const xmlnode *node) | 279 const char *xmlnode_get_namespace(const xmlnode *node) |
| 272 { | 280 { |
| 273 g_return_val_if_fail(node != NULL, NULL); | 281 g_return_val_if_fail(node != NULL, NULL); |
| 275 return node->xmlns; | 283 return node->xmlns; |
| 276 } | 284 } |
| 277 | 285 |
| 278 const char *xmlnode_get_default_namespace(const xmlnode *node) | 286 const char *xmlnode_get_default_namespace(const xmlnode *node) |
| 279 { | 287 { |
| 288 const xmlnode *current_node; | |
| 280 const char *ns = NULL; | 289 const char *ns = NULL; |
| 290 | |
| 281 g_return_val_if_fail(node != NULL, NULL); | 291 g_return_val_if_fail(node != NULL, NULL); |
| 282 | 292 |
| 283 /* If this node does *not* have a prefix, node->xmlns is the default | 293 current_node = node; |
| 284 * namespace. Otherwise, it's the prefix namespace. | 294 while (current_node) { |
| 285 */ | 295 /* If this node does *not* have a prefix, node->xmlns is the default |
| 286 if (!node->prefix && node->xmlns) { | 296 * namespace. Otherwise, it's the prefix namespace. |
| 287 return node->xmlns; | 297 */ |
| 288 } else if (node->namespace_map) { | 298 if (!current_node->prefix && current_node->xmlns) { |
| 289 ns = g_hash_table_lookup(node->namespace_map, ""); | 299 return current_node->xmlns; |
| 290 } | 300 } else if (current_node->namespace_map) { |
| 291 | 301 ns = g_hash_table_lookup(current_node->namespace_map, ""); |
| 292 /* No default ns found? Walk up the tree looking for one */ | 302 if (ns && *ns) |
| 293 if (!(ns && *ns) && node->parent) | 303 return ns; |
| 294 ns = xmlnode_get_default_namespace(node->parent); | 304 } |
| 305 | |
| 306 current_node = current_node->parent; | |
| 307 } | |
| 295 | 308 |
| 296 return ns; | 309 return ns; |
| 297 } | 310 } |
| 298 | 311 |
| 299 void xmlnode_set_prefix(xmlnode *node, const char *prefix) | 312 void xmlnode_set_prefix(xmlnode *node, const char *prefix) |
| 306 | 319 |
| 307 const char *xmlnode_get_prefix(const xmlnode *node) | 320 const char *xmlnode_get_prefix(const xmlnode *node) |
| 308 { | 321 { |
| 309 g_return_val_if_fail(node != NULL, NULL); | 322 g_return_val_if_fail(node != NULL, NULL); |
| 310 return node->prefix; | 323 return node->prefix; |
| 324 } | |
| 325 | |
| 326 const char *xmlnode_get_prefix_namespace(const xmlnode *node, const char *prefix) | |
| 327 { | |
| 328 const xmlnode *current_node; | |
| 329 | |
| 330 g_return_val_if_fail(node != NULL, NULL); | |
| 331 g_return_val_if_fail(prefix != NULL, xmlnode_get_default_namespace(node)); | |
| 332 | |
| 333 current_node = node; | |
| 334 while (current_node) { | |
| 335 if (current_node->prefix && g_str_equal(prefix, current_node->prefix) && | |
| 336 current_node->xmlns) { | |
| 337 return current_node->xmlns; | |
| 338 } else if (current_node->namespace_map) { | |
| 339 const char *ns = g_hash_table_lookup(current_node->namespace_map, prefix); | |
| 340 if (ns && *ns) { | |
| 341 return ns; | |
| 342 } | |
| 343 } | |
| 344 | |
| 345 current_node = current_node->parent; | |
| 346 } | |
| 347 | |
| 348 return NULL; | |
| 349 } | |
| 350 | |
| 351 void xmlnode_strip_prefixes(xmlnode *node) | |
| 352 { | |
| 353 xmlnode *child; | |
| 354 const char *prefix; | |
| 355 | |
| 356 g_return_if_fail(node != NULL); | |
| 357 | |
| 358 for (child = node->child; child; child = child->next) { | |
| 359 if (child->type == XMLNODE_TYPE_TAG) | |
| 360 xmlnode_strip_prefixes(child); | |
| 361 } | |
| 362 | |
| 363 prefix = xmlnode_get_prefix(node); | |
| 364 if (prefix) { | |
| 365 const char *ns = xmlnode_get_prefix_namespace(node, prefix); | |
| 366 xmlnode_set_namespace(node, ns); | |
| 367 xmlnode_set_prefix(node, NULL); | |
| 368 } else { | |
| 369 xmlnode_set_namespace(node, xmlnode_get_default_namespace(node)); | |
| 370 } | |
| 311 } | 371 } |
| 312 | 372 |
| 313 xmlnode *xmlnode_get_parent(const xmlnode *child) | 373 xmlnode *xmlnode_get_parent(const xmlnode *child) |
| 314 { | 374 { |
| 315 g_return_val_if_fail(child != NULL, NULL); | 375 g_return_val_if_fail(child != NULL, NULL); |
