| 170 } |
173 } |
| 171 |
174 |
| 172 return NULL; |
175 return NULL; |
| 173 } |
176 } |
| 174 |
177 |
| |
178 |
| |
179 void xmlnode_set_namespace(xmlnode *node, const char *xmlns) |
| |
180 { |
| |
181 #ifdef HAVE_LIBXML |
| |
182 g_return_if_fail(node != NULL); |
| |
183 |
| |
184 if (node->namespace) |
| |
185 g_free(node->namespace); |
| |
186 |
| |
187 node->namespace = g_strdup(xmlns); |
| |
188 #else |
| |
189 return xmlnode_set_attrib(node, "xmlns", xmlns); |
| |
190 #endif |
| |
191 } |
| |
192 |
| |
193 const char *xmlnode_get_namespace(xmlnode *node) |
| |
194 { |
| |
195 #ifdef HAVE_LIBXML |
| |
196 g_return_val_if_fail(node != NULL, NULL); |
| |
197 |
| |
198 return node->namespace; |
| |
199 #else |
| |
200 return xmlnode_get_attrib(node, "xmlns"); |
| |
201 #endif |
| |
202 } |
| |
203 |
| 175 void |
204 void |
| 176 xmlnode_free(xmlnode *node) |
205 xmlnode_free(xmlnode *node) |
| 177 { |
206 { |
| 178 xmlnode *x, *y; |
207 xmlnode *x, *y; |
| 179 |
208 |
| 214 child_name = names[1]; |
247 child_name = names[1]; |
| 215 |
248 |
| 216 for(x = parent->child; x; x = x->next) { |
249 for(x = parent->child; x; x = x->next) { |
| 217 const char *xmlns = NULL; |
250 const char *xmlns = NULL; |
| 218 if(ns) |
251 if(ns) |
| 219 xmlns = xmlnode_get_attrib(x, "xmlns"); |
252 xmlns = xmlnode_get_namespace(x); |
| 220 |
253 |
| 221 if(x->type == XMLNODE_TYPE_TAG && name && !strcmp(parent_name, x->name) |
254 if(x->type == XMLNODE_TYPE_TAG && name && !strcmp(parent_name, x->name) |
| 222 && (!ns || (xmlns && !strcmp(ns, xmlns)))) { |
255 && (!ns || (xmlns && !strcmp(ns, xmlns)))) { |
| 223 ret = x; |
256 ret = x; |
| 224 break; |
257 break; |
| 270 } |
303 } |
| 271 |
304 |
| 272 node_name = g_markup_escape_text(node->name, -1); |
305 node_name = g_markup_escape_text(node->name, -1); |
| 273 g_string_append_printf(text, "<%s", node_name); |
306 g_string_append_printf(text, "<%s", node_name); |
| 274 |
307 |
| |
308 #ifdef HAVE_LIBXML |
| |
309 if (node->namespace) { |
| |
310 char *namespace = g_markup_escape_text(node->namespace, -1); |
| |
311 g_string_append_printf(text, " xmlns='%s'", namespace); |
| |
312 g_free(namespace); |
| |
313 } |
| |
314 #endif |
| 275 for(c = node->child; c; c = c->next) |
315 for(c = node->child; c; c = c->next) |
| 276 { |
316 { |
| 277 if(c->type == XMLNODE_TYPE_ATTRIB) { |
317 if(c->type == XMLNODE_TYPE_ATTRIB) { |
| 278 esc = g_markup_escape_text(c->name, -1); |
318 esc = g_markup_escape_text(c->name, -1); |
| 279 esc2 = g_markup_escape_text(c->data, -1); |
319 esc2 = g_markup_escape_text(c->data, -1); |
| 345 |
385 |
| 346 struct _xmlnode_parser_data { |
386 struct _xmlnode_parser_data { |
| 347 xmlnode *current; |
387 xmlnode *current; |
| 348 }; |
388 }; |
| 349 |
389 |
| |
390 #ifdef HAVE_LIBXML |
| 350 static void |
391 static void |
| 351 xmlnode_parser_element_start(GMarkupParseContext *context, |
392 xmlnode_parser_element_start_libxml(void *user_data, |
| 352 const char *element_name, const char **attrib_names, |
393 const xmlChar *element_name, const xmlChar *prefix, const xmlChar *namespace, |
| 353 const char **attrib_values, gpointer user_data, GError **error) |
394 int nb_namespaces, const xmlChar **namespaces, |
| |
395 int nb_attributes, int nb_defaulted, const xmlChar **attributes) |
| 354 { |
396 { |
| 355 struct _xmlnode_parser_data *xpd = user_data; |
397 struct _xmlnode_parser_data *xpd = user_data; |
| 356 xmlnode *node; |
398 xmlnode *node; |
| 357 int i; |
399 int i; |
| 358 |
400 |
| 362 if(xpd->current) |
404 if(xpd->current) |
| 363 node = xmlnode_new_child(xpd->current, element_name); |
405 node = xmlnode_new_child(xpd->current, element_name); |
| 364 else |
406 else |
| 365 node = xmlnode_new(element_name); |
407 node = xmlnode_new(element_name); |
| 366 |
408 |
| |
409 xmlnode_set_namespace(node, namespace); |
| |
410 |
| |
411 for(i=0; i < nb_attributes * 5; i+=5) { |
| |
412 int attrib_len = attributes[i+4] - attributes[i+3]; |
| |
413 char *attrib = g_malloc(attrib_len + 1); |
| |
414 memcpy(attrib, attributes[i+3], attrib_len); |
| |
415 attrib[attrib_len] = '\0'; |
| |
416 xmlnode_set_attrib(node, attributes[i], attrib); |
| |
417 g_free(attrib); |
| |
418 } |
| |
419 |
| |
420 xpd->current = node; |
| |
421 } |
| |
422 } |
| |
423 |
| |
424 static void |
| |
425 xmlnode_parser_element_end_libxml(void *user_data, const xmlChar *element_name, |
| |
426 const xmlChar *prefix, const xmlChar *namespace) |
| |
427 { |
| |
428 struct _xmlnode_parser_data *xpd = user_data; |
| |
429 |
| |
430 if(!element_name || !xpd->current) |
| |
431 return; |
| |
432 |
| |
433 if(xpd->current->parent) { |
| |
434 if(!strcmp(xpd->current->name, element_name)) |
| |
435 xpd->current = xpd->current->parent; |
| |
436 } |
| |
437 } |
| |
438 |
| |
439 static void |
| |
440 xmlnode_parser_element_text_libxml(void *user_data, const xmlChar *text, int text_len) |
| |
441 { |
| |
442 struct _xmlnode_parser_data *xpd = user_data; |
| |
443 |
| |
444 if(!xpd->current) |
| |
445 return; |
| |
446 |
| |
447 if(!text || !text_len) |
| |
448 return; |
| |
449 |
| |
450 xmlnode_insert_data(xpd->current, text, text_len); |
| |
451 } |
| |
452 |
| |
453 #else |
| |
454 |
| |
455 static void |
| |
456 xmlnode_parser_element_start(GMarkupParseContext *context, |
| |
457 const char *element_name, const char **attrib_names, |
| |
458 const char **attrib_values, gpointer user_data, GError **error) |
| |
459 { |
| |
460 struct _xmlnode_parser_data *xpd = user_data; |
| |
461 xmlnode *node; |
| |
462 int i; |
| |
463 |
| |
464 if(!element_name) { |
| |
465 return; |
| |
466 } else { |
| |
467 if(xpd->current) |
| |
468 node = xmlnode_new_child(xpd->current, element_name); |
| |
469 else |
| |
470 node = xmlnode_new(element_name); |
| |
471 |
| 367 for(i=0; attrib_names[i]; i++) |
472 for(i=0; attrib_names[i]; i++) |
| 368 xmlnode_set_attrib(node, attrib_names[i], attrib_values[i]); |
473 xmlnode_set_attrib(node, attrib_names[i], attrib_values[i]); |
| 369 |
474 |
| 370 xpd->current = node; |
475 xpd->current = node; |
| 371 } |
476 } |
| 398 if(!text || !text_len) |
503 if(!text || !text_len) |
| 399 return; |
504 return; |
| 400 |
505 |
| 401 xmlnode_insert_data(xpd->current, text, text_len); |
506 xmlnode_insert_data(xpd->current, text, text_len); |
| 402 } |
507 } |
| 403 |
508 #endif |
| |
509 |
| |
510 #ifdef HAVE_LIBXML |
| |
511 static xmlSAXHandler xmlnode_parser_libxml = { |
| |
512 .internalSubset = NULL, |
| |
513 .isStandalone = NULL, |
| |
514 .hasInternalSubset = NULL, |
| |
515 .hasExternalSubset = NULL, |
| |
516 .resolveEntity = NULL, |
| |
517 .getEntity = NULL, |
| |
518 .entityDecl = NULL, |
| |
519 .notationDecl = NULL, |
| |
520 .attributeDecl = NULL, |
| |
521 .elementDecl = NULL, |
| |
522 .unparsedEntityDecl = NULL, |
| |
523 .setDocumentLocator = NULL, |
| |
524 .startDocument = NULL, |
| |
525 .endDocument = NULL, |
| |
526 .startElement = NULL, |
| |
527 .endElement = NULL, |
| |
528 .reference = NULL, |
| |
529 .characters = xmlnode_parser_element_text_libxml, |
| |
530 .ignorableWhitespace = NULL, |
| |
531 .processingInstruction = NULL, |
| |
532 .comment = NULL, |
| |
533 .warning = NULL, |
| |
534 .error = NULL, |
| |
535 .fatalError = NULL, |
| |
536 .getParameterEntity = NULL, |
| |
537 .cdataBlock = NULL, |
| |
538 .externalSubset = NULL, |
| |
539 .initialized = XML_SAX2_MAGIC, |
| |
540 ._private = NULL, |
| |
541 .startElementNs = xmlnode_parser_element_start_libxml, |
| |
542 .endElementNs = xmlnode_parser_element_end_libxml, |
| |
543 .serror = NULL |
| |
544 }; |
| |
545 #else |
| 404 static GMarkupParser xmlnode_parser = { |
546 static GMarkupParser xmlnode_parser = { |
| 405 xmlnode_parser_element_start, |
547 xmlnode_parser_element_start, |
| 406 xmlnode_parser_element_end, |
548 xmlnode_parser_element_end, |
| 407 xmlnode_parser_element_text, |
549 xmlnode_parser_element_text, |
| 408 NULL, |
550 NULL, |
| 409 NULL |
551 NULL |
| 410 }; |
552 }; |
| 411 |
553 #endif |
| 412 |
554 |
| 413 xmlnode * |
555 xmlnode * |
| 414 xmlnode_from_str(const char *str, gssize size) |
556 xmlnode_from_str(const char *str, gssize size) |
| 415 { |
557 { |
| 416 struct _xmlnode_parser_data *xpd; |
558 struct _xmlnode_parser_data *xpd; |
| 420 |
562 |
| 421 g_return_val_if_fail(str != NULL, NULL); |
563 g_return_val_if_fail(str != NULL, NULL); |
| 422 |
564 |
| 423 real_size = size < 0 ? strlen(str) : size; |
565 real_size = size < 0 ? strlen(str) : size; |
| 424 xpd = g_new0(struct _xmlnode_parser_data, 1); |
566 xpd = g_new0(struct _xmlnode_parser_data, 1); |
| |
567 |
| |
568 #ifdef HAVE_LIBXML |
| |
569 if (xmlSAXUserParseMemory(&xmlnode_parser_libxml, xpd, str, size) < 0) { |
| |
570 while(xpd->current && xpd->current->parent) |
| |
571 xpd->current = xpd->current->parent; |
| |
572 if(xpd->current) |
| |
573 xmlnode_free(xpd->current); |
| |
574 xpd->current = NULL; |
| |
575 } |
| |
576 #else |
| 425 context = g_markup_parse_context_new(&xmlnode_parser, 0, xpd, NULL); |
577 context = g_markup_parse_context_new(&xmlnode_parser, 0, xpd, NULL); |
| 426 |
578 |
| 427 if(!g_markup_parse_context_parse(context, str, real_size, NULL)) { |
579 if(!g_markup_parse_context_parse(context, str, real_size, NULL)) { |
| 428 while(xpd->current && xpd->current->parent) |
580 while(xpd->current && xpd->current->parent) |
| 429 xpd->current = xpd->current->parent; |
581 xpd->current = xpd->current->parent; |
| 430 if(xpd->current) |
582 if(xpd->current) |
| 431 xmlnode_free(xpd->current); |
583 xmlnode_free(xpd->current); |
| 432 xpd->current = NULL; |
584 xpd->current = NULL; |
| 433 } |
585 } |
| 434 g_markup_parse_context_free(context); |
586 g_markup_parse_context_free(context); |
| 435 |
587 #endif |
| 436 ret = xpd->current; |
588 ret = xpd->current; |
| 437 g_free(xpd); |
589 g_free(xpd); |
| 438 return ret; |
590 return ret; |
| 439 } |
591 } |
| 440 |
592 |
| 475 |
627 |
| 476 xmlnode * |
628 xmlnode * |
| 477 xmlnode_get_next_twin(xmlnode *node) |
629 xmlnode_get_next_twin(xmlnode *node) |
| 478 { |
630 { |
| 479 xmlnode *sibling; |
631 xmlnode *sibling; |
| 480 const char *ns = xmlnode_get_attrib(node, "xmlns"); |
632 const char *ns = xmlnode_get_namespace(node); |
| 481 |
633 |
| 482 g_return_val_if_fail(node != NULL, NULL); |
634 g_return_val_if_fail(node != NULL, NULL); |
| 483 g_return_val_if_fail(node->type == XMLNODE_TYPE_TAG, NULL); |
635 g_return_val_if_fail(node->type == XMLNODE_TYPE_TAG, NULL); |
| 484 |
636 |
| 485 for(sibling = node->next; sibling; sibling = sibling->next) { |
637 for(sibling = node->next; sibling; sibling = sibling->next) { |
| 486 const char *xmlns = NULL; |
638 const char *xmlns = NULL; |
| 487 if(ns) |
639 if(ns) |
| 488 xmlns = xmlnode_get_attrib(sibling, "xmlns"); |
640 xmlns = xmlnode_get_namespace(sibling); |
| 489 |
641 |
| 490 if(sibling->type == XMLNODE_TYPE_TAG && !strcmp(node->name, sibling->name) && |
642 if(sibling->type == XMLNODE_TYPE_TAG && !strcmp(node->name, sibling->name) && |
| 491 (!ns || (xmlns && !strcmp(ns, xmlns)))) |
643 (!ns || (xmlns && !strcmp(ns, xmlns)))) |
| 492 return sibling; |
644 return sibling; |
| 493 } |
645 } |