<libroxml  version="3.0.2" />
contact: tristan.lelong@libroxml.net
roxml_core.c
Go to the documentation of this file.
1
12#include <stdlib.h>
13#include <string.h>
14#include "roxml_core.h"
15#include "roxml_file.h"
16#include "roxml_buff.h"
17#include "roxml_parser.h"
18
19#ifdef __DEBUG
20unsigned int _nb_node = 0;
21unsigned int _nb_attr = 0;
22unsigned int _nb_text = 0;
23#endif
24
26{
27 node_t *root = n;
28
29 if (root == ROXML_INVALID_DOC)
30 return;
31
32 while (root->prnt != NULL)
33 root = root->prnt;
34
35 roxml_del_tree(root->chld);
36 roxml_del_tree(root->sibl);
37
38 if ((root->type & ROXML_FILE) == ROXML_FILE)
39 roxml_close_file(root);
40 else
41 roxml_close_buff(root);
42
43 roxml_free_node(root);
44}
45
46ROXML_INT node_t *roxml_create_node(int pos, void *src, int type)
47{
48 node_t *n = (node_t *)calloc(1, sizeof(node_t));
49 n->type = type;
50 n->src.src = src;
51 n->pos = pos;
52 n->end = pos;
53
54 return n;
55}
56
65ROXML_STATIC ROXML_INT void roxml_close_node(node_t *n, node_t *close)
66{
67 if (n) {
68 n->end = close->pos;
69 free(close);
70
71#ifdef __DEBUG
72 if (n->type & ROXML_ELM_NODE)
73 _nb_node++;
74 if (n->type & ROXML_ATTR_NODE)
75 _nb_attr++;
76 if (n->type & ROXML_TXT_NODE)
77 _nb_text++;
78#endif
79 }
80}
81
82ROXML_INT void roxml_free_node(node_t *n)
83{
84 if (!n)
85 return;
86
87 if (n->type & ROXML_PENDING)
88 if (n->pos == 0)
89 free(n->src.buf);
90
91 if (n->priv) {
92 unsigned char id = *(unsigned char *)n->priv;
93
94 if (id == ROXML_REQTABLE_ID) {
95 xpath_tok_t *tok;
97
98 roxml_lock_destroy(n);
99
100 tok = table->next;
101 free(table);
102 while (tok) {
103 xpath_tok_t *to_delete = tok;
104 tok = tok->next;
105 free(to_delete);
106 }
107 } else if (id == ROXML_NS_ID) {
108 roxml_ns_t *ns = (roxml_ns_t *)n->priv;
109 free(ns);
110 }
111 }
112 free(n);
113}
114
115ROXML_INT void roxml_del_tree(node_t *n)
116{
117 if (n == NULL)
118 return;
119
120 if (n != n->chld)
122 if (n != n->sibl)
126}
127
128ROXML_INT inline int roxml_is_separator(char sep)
129{
130 int i = 0;
131 char separators[32] = "\r\t\n ";
132
133 while (separators[i] != 0)
134 if (sep == separators[i++])
135 return 1;
136 return 0;
137}
138
146ROXML_STATIC ROXML_INT void roxml_process_unaliased_ns(roxml_load_ctx_t *context)
147{
148 if (context->nsdef) {
149 context->nsdef = 0;
150 context->candidat_arg->type |= ROXML_NS_NODE;
151
152 if (context->candidat_node->ns && ((context->candidat_node->ns->type & ROXML_INVALID) == ROXML_INVALID))
154
155 if (context->candidat_val->pos == context->candidat_val->end) {
156 context->candidat_node->ns = NULL;
157 context->candidat_arg->ns = NULL;
158 } else {
159 roxml_ns_t *ns = calloc(1, sizeof(roxml_ns_t) + 1);
160 ns->id = ROXML_NS_ID;
161 ns->alias = (char *)ns + sizeof(roxml_ns_t);
162
163 context->candidat_arg->priv = ns;
164 context->candidat_arg->ns = context->candidat_arg;
165 context->candidat_node->ns = context->candidat_arg;
166
167 context->namespaces = context->candidat_arg;
168 }
169 }
170}
171
180ROXML_STATIC ROXML_INT void roxml_process_begin_node(roxml_load_ctx_t *context, int position)
181{
182 if (context->candidat_txt) {
183#ifdef IGNORE_EMPTY_TEXT_NODES
184 if (context->empty_text_node == 0) {
185#endif /* IGNORE_EMPTY_TEXT_NODES */
186 node_t *to_be_closed =
187 roxml_create_node(position, context->src, ROXML_TXT_NODE | context->type);
188 context->candidat_txt = roxml_append_node(context->current_node, context->candidat_txt);
189 roxml_close_node(context->candidat_txt, to_be_closed);
190 context->current_node = context->candidat_txt->prnt;
191#ifdef IGNORE_EMPTY_TEXT_NODES
192 } else {
194 }
195#endif /* IGNORE_EMPTY_TEXT_NODES */
196 context->candidat_txt = NULL;
197 }
198 context->candidat_node = roxml_create_node(position, context->src, ROXML_ELM_NODE | context->type);
199}
200
201ROXML_INT node_t *roxml_load(node_t *current_node, FILE *file, char *buffer)
202{
203 int error = 0;
204 node_t *root = current_node;
205 roxml_load_ctx_t context;
206 roxml_parser_item_t *parser = NULL;
207
208 memset(&context, 0, sizeof(roxml_load_ctx_t));
209 context.empty_text_node = 1;
210 context.current_node = current_node;
211
212 parser = roxml_append_parser_item(parser, " ", _func_load_white);
213 parser = roxml_append_parser_item(parser, "<", _func_load_open_node);
214 parser = roxml_append_parser_item(parser, ">", _func_load_close_node);
215 parser = roxml_append_parser_item(parser, "/", _func_load_end_node);
216 parser = roxml_append_parser_item(parser, "'", _func_load_quoted);
217 parser = roxml_append_parser_item(parser, "\"", _func_load_dquoted);
218 parser = roxml_append_parser_item(parser, "\t", _func_load_white);
219 parser = roxml_append_parser_item(parser, "\n", _func_load_white);
220 parser = roxml_append_parser_item(parser, "\r", _func_load_white);
221 parser = roxml_append_parser_item(parser, "!", _func_load_open_spec_node);
222 parser = roxml_append_parser_item(parser, "]", _func_load_close_cdata);
223 parser = roxml_append_parser_item(parser, "-", _func_load_close_comment);
224 parser = roxml_append_parser_item(parser, "?", _func_load_close_pi);
225 parser = roxml_append_parser_item(parser, ":", _func_load_colon);
226 parser = roxml_append_parser_item(parser, "", _func_load_default);
227
228 parser = roxml_parser_prepare(parser);
229
230 if (file)
231 error = roxml_parse_file(&context, parser, file);
232 else
233 error = roxml_parse_buff(&context, parser, buffer);
234
235 roxml_parser_free(parser);
236
237 if (context.empty_text_node == 1) {
239 } else if (context.candidat_txt) {
240 node_t *to_be_closed = roxml_create_node(context.pos, context.src, ROXML_TXT_NODE | context.type);
241 context.candidat_txt = roxml_append_node(context.current_node, context.candidat_txt);
242 roxml_close_node(context.candidat_txt, to_be_closed);
243 }
244 current_node = NULL;
245
246 if (error == 0) {
247 current_node = roxml_create_root(root);
248 } else {
249 roxml_close(root);
250 current_node = ROXML_INVALID_DOC;
251 }
252
253 return current_node;
254}
255
257{
258 xpath_tok_table_t *table = (xpath_tok_table_t *)calloc(1, sizeof(xpath_tok_table_t));
259
260 table->id = ROXML_REQTABLE_ID;
261 table->ids[ROXML_REQTABLE_ID] = 1;
262
263 n->priv = (void *)table;
264
265 roxml_lock_init(n);
266
267 return n;
268}
269
278ROXML_STATIC ROXML_INT node_t *roxml_lookup_nsdef(node_t *nsdef, char *ns)
279{
280 int len = 0;
281 char namespace[MAX_NAME_LEN];
282
283 for (len = 0; ns[len] != '\0' && ns[len] != ':' && len < MAX_NAME_LEN; len++)
284 namespace[len] = ns[len];
285
286 if (len == MAX_NAME_LEN)
287 return NULL; /* truncated */
288
289 namespace[len] = '\0';
290
291 while (nsdef) {
292 if (nsdef->priv && strcmp(namespace, ((roxml_ns_t *)nsdef->priv)->alias) == 0)
293 break;
294 nsdef = nsdef->next;
295 }
296 return nsdef;
297}
298
307ROXML_STATIC ROXML_INT inline void roxml_set_type(node_t *n, int type)
308{
310 n->type |= type;
311}
312
313ROXML_INT node_t *roxml_set_parent(node_t *parent, node_t *n)
314{
315 if (parent == NULL)
316 return NULL;
317
318 n->prnt = parent;
319
320 if (parent->ns && ((parent->ns->type & ROXML_INVALID) != ROXML_INVALID)
321 && parent->ns->priv && ((roxml_ns_t *)parent->ns->priv)->alias[0] == '\0')
322 if (n->ns == NULL)
323 n->ns = parent->ns;
324 return n;
325}
326
327ROXML_STATIC ROXML_INT node_t *roxml_append_attr(node_t *parent, node_t *n)
328{
329 if (parent->attr) {
330 node_t *attr = parent->attr;
331 while (attr->sibl)
332 attr = attr->sibl;
333 attr->sibl = n;
334 } else {
335 parent->attr = n;
336 }
337
338 return n;
339}
340
341ROXML_STATIC ROXML_INT node_t *roxml_append_other(node_t *parent, node_t *n)
342{
343 if (parent->next)
344 parent->next->sibl = n;
345 else
346 parent->chld = n;
347 parent->next = n;
348
349 return n;
350}
351
352ROXML_INT node_t *roxml_append_node(node_t *parent, node_t *n)
353{
354 if (!roxml_set_parent(parent, n))
355 return n;
356
357 if (n->type & ROXML_ATTR_NODE)
358 roxml_append_attr(parent, n);
359 else
360 roxml_append_other(parent, n);
361
362 return n;
363}
364
365ROXML_INT int _func_load_quoted(roxml_parser_item_t *parser, char *chunk, void *data)
366{
367#ifdef DEBUG_PARSING
368 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
369#endif /* DEBUG_PARSING */
370 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
371
372 if (context->state != STATE_NODE_CONTENT && context->state != STATE_NODE_COMMENT && context->state != STATE_NODE_CDATA) {
373 if (context->mode == MODE_COMMENT_NONE)
374 context->mode = MODE_COMMENT_QUOTE;
375 else if (context->mode == MODE_COMMENT_QUOTE)
376 context->mode = MODE_COMMENT_NONE;
377 }
378
379 return 0;
380}
381
382ROXML_INT int _func_load_dquoted(roxml_parser_item_t *parser, char *chunk, void *data)
383{
384#ifdef DEBUG_PARSING
385 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
386#endif /* DEBUG_PARSING */
387 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
388
389 if (context->state != STATE_NODE_CONTENT && context->state != STATE_NODE_COMMENT && context->state != STATE_NODE_CDATA) {
390 if (context->mode == MODE_COMMENT_NONE)
391 context->mode = MODE_COMMENT_DQUOTE;
392 else if (context->mode == MODE_COMMENT_DQUOTE)
393 context->mode = MODE_COMMENT_NONE;
394 }
395
396 return 0;
397}
398
399ROXML_INT int _func_load_open_node(roxml_parser_item_t *parser, char *chunk, void *data)
400{
401#ifdef DEBUG_PARSING
402 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
403#endif /* DEBUG_PARSING */
404 int cur = 1;
405 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
406
407 switch (context->state) {
408 case STATE_NODE_CDATA:
410 break;
411 case STATE_NODE_ATTR:
412 case STATE_NODE_BEG:
413 if (context->mode == MODE_COMMENT_NONE)
414 ROXML_PARSE_ERROR("unexpected '<' within node definition");
415 break;
416 default:
417 context->state = STATE_NODE_BEG;
419 break;
420 }
421
422 context->pos += cur;
423 return cur;
424}
425
426ROXML_INT int _func_load_close_node(roxml_parser_item_t *parser, char *chunk, void *data)
427{
428#ifdef DEBUG_PARSING
429 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
430#endif /* DEBUG_PARSING */
431 int cur = 1;
432 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
433
434 switch (context->state) {
435 case STATE_NODE_NAME:
436 context->empty_text_node = 1;
437 context->current_node = roxml_append_node(context->current_node, context->candidat_node);
438 break;
439 case STATE_NODE_ATTR:
440 if ((context->mode != MODE_COMMENT_DQUOTE) && (context->mode != MODE_COMMENT_QUOTE)) {
441 if (context->inside_node_state == STATE_INSIDE_VAL) {
442 node_t *to_be_closed = NULL;
443 if (context->content_quoted) {
444 context->content_quoted = 0;
445 to_be_closed =
446 roxml_create_node(context->pos - 1, context->src,
447 ROXML_ATTR_NODE | context->type);
448 } else {
449 to_be_closed =
450 roxml_create_node(context->pos, context->src,
451 ROXML_ATTR_NODE | context->type);
452 }
453 roxml_close_node(context->candidat_val, to_be_closed);
454 }
455 context->current_node = roxml_append_node(context->current_node, context->candidat_node);
458 } else {
459 context->pos++;
460 return 1;
461 }
462 break;
464 if (context->doctype) {
465 context->doctype--;
466 if (context->doctype > 0) {
467 context->pos++;
468 return 1;
469 }
470 context->candidat_node->end = context->pos;
471 }
472 context->empty_text_node = 1;
473 context->current_node = roxml_append_node(context->current_node, context->candidat_node);
474 if (context->current_node->prnt != NULL) {
475 context->current_node = context->current_node->prnt;
476 }
478 break;
479 case STATE_NODE_END:
480 context->empty_text_node = 1;
481 roxml_close_node(context->current_node, context->candidat_node);
482 context->candidat_node = NULL;
483 if (context->current_node->prnt != NULL) {
484 context->current_node = context->current_node->prnt;
485 }
486 break;
487 case STATE_NODE_CDATA:
489 default:
490 context->pos++;
491 return 1;
492 break;
493 }
494
495 if (context->candidat_node && context->candidat_node->ns
496 && ((context->candidat_node->ns->type & ROXML_INVALID) == ROXML_INVALID)) {
498 context->candidat_node->ns = NULL;
499 }
500
501 context->state = STATE_NODE_CONTENT;
503 context->candidat_txt = roxml_create_node(context->pos + 1, context->src, ROXML_TXT_NODE | context->type);
504#ifdef IGNORE_EMPTY_TEXT_NODES
505 while (chunk[cur] != '\0') {
506 if (chunk[cur] == '<') {
507 break;
508 } else if (!ROXML_WHITE(chunk[cur])) {
509 context->empty_text_node = 0;
510 break;
511 }
512 cur++;
513 }
514#endif /* IGNORE_EMPTY_TEXT_NODES */
515 while ((chunk[cur] != '<') && (chunk[cur] != '\0'))
516 cur++;
517
518 context->pos += cur;
519 return cur;
520}
521
522ROXML_INT int _func_load_open_spec_node(roxml_parser_item_t *parser, char *chunk, void *data)
523{
524#ifdef DEBUG_PARSING
525 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
526#endif /* DEBUG_PARSING */
527 int cur = 1;
528
529 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
530
531 if (context->state == STATE_NODE_BEG) {
532 if (strncmp(chunk, "!--", 3) == 0) {
533 cur = 3;
534 roxml_process_begin_node(context, context->pos - 1);
536 context->state = STATE_NODE_COMMENT;
537 while ((chunk[cur] != '-') && (chunk[cur] != '\0'))
538 cur++;
539 } else if (strncmp(chunk, "![CDATA[", 8) == 0) {
540 roxml_process_begin_node(context, context->pos - 1);
542 context->state = STATE_NODE_CDATA;
543 while ((chunk[cur] != '[') && (chunk[cur] != '\0'))
544 cur++;
545 } else {
546 if (context->doctype == 0) {
547 roxml_process_begin_node(context, context->pos - 1);
549 }
550 context->state = STATE_NODE_SINGLE;
552 context->doctype++;
553 }
554 }
555
556 context->pos += cur;
557 return cur;
558}
559
560ROXML_INT int _func_load_close_comment(roxml_parser_item_t *parser, char *chunk, void *data)
561{
562#ifdef DEBUG_PARSING
563 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
564#endif /* DEBUG_PARSING */
565 int cur = 1;
566 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
567
568 if (context->state == STATE_NODE_COMMENT) {
569 if (chunk[1] == '-') {
570 cur = 2;
571 context->state = STATE_NODE_SINGLE;
572 context->candidat_node->end = context->pos;
573 }
574 }
575
576 context->pos += cur;
577 return cur;
578}
579
580ROXML_INT int _func_load_close_cdata(roxml_parser_item_t *parser, char *chunk, void *data)
581{
582#ifdef DEBUG_PARSING
583 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
584#endif /* DEBUG_PARSING */
585 int cur = 1;
586 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
587
588 if (context->state == STATE_NODE_CDATA) {
589 if (chunk[1] == ']') {
590 cur = 2;
591 context->state = STATE_NODE_SINGLE;
592 context->candidat_node->pos += 9;
593 context->candidat_node->end = context->pos;
594 }
595 }
596
597 context->pos += cur;
598 return cur;
599}
600
601ROXML_INT int _func_load_close_pi(roxml_parser_item_t *parser, char *chunk, void *data)
602{
603#ifdef DEBUG_PARSING
604 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
605#endif /* DEBUG_PARSING */
606 int cur = 1;
607 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
608
609 if (context->state == STATE_NODE_BEG) {
610 cur = 1;
611 context->state = STATE_NODE_PI;
612 context->previous_state = STATE_NODE_PI;
613 roxml_process_begin_node(context, context->pos - 1);
615 // while((chunk[cur] != '?')&&(chunk[cur] != '\0')) { cur++; }
616 } else if (context->state == STATE_NODE_PI) {
617 if (context->mode == MODE_COMMENT_NONE) {
618 cur = 1;
619 context->candidat_node->end = context->pos;
620 context->previous_state = STATE_NODE_PI;
621 context->state = STATE_NODE_SINGLE;
622 }
623 }
624
625 context->pos += cur;
626 return cur;
627}
628
629ROXML_INT int _func_load_end_node(roxml_parser_item_t *parser, char *chunk, void *data)
630{
631#ifdef DEBUG_PARSING
632 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
633#endif /* DEBUG_PARSING */
634 int cur = 1;
635 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
636
637 switch (context->state) {
638 case STATE_NODE_BEG:
639 context->lvl--;
640 roxml_process_begin_node(context, context->pos - 1);
641 context->state = STATE_NODE_END;
642 if (context->lvl < 0)
643 ROXML_PARSE_ERROR("missing opening node");
644 break;
645 case STATE_NODE_NAME:
646 context->lvl--;
647 context->state = STATE_NODE_SINGLE;
648 break;
649 case STATE_NODE_ATTR:
650 if ((context->mode != MODE_COMMENT_DQUOTE) && (context->mode != MODE_COMMENT_QUOTE)) {
651 if (context->inside_node_state == STATE_INSIDE_VAL) {
652 node_t *to_be_closed = NULL;
653 if (context->content_quoted) {
654 context->content_quoted = 0;
655 to_be_closed =
656 roxml_create_node(context->pos - 1, context->src,
657 ROXML_ATTR_NODE | context->type);
658 } else {
659 to_be_closed =
660 roxml_create_node(context->pos, context->src,
661 ROXML_ATTR_NODE | context->type);
662 }
663 roxml_close_node(context->candidat_val, to_be_closed);
664 }
666 context->state = STATE_NODE_SINGLE;
667 context->lvl--;
668 }
669 break;
670 }
671
672 context->pos += cur;
673 return cur;
674}
675
676ROXML_INT int _func_load_white(roxml_parser_item_t *parser, char *chunk, void *data)
677{
678#ifdef DEBUG_PARSING
679 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
680#endif /* DEBUG_PARSING */
681 int cur = 1;
682 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
683
684 switch (context->state) {
686 context->state = context->previous_state;
687 break;
688 case STATE_NODE_NAME:
689 context->state = STATE_NODE_ATTR;
691 break;
692 case STATE_NODE_ATTR:
693 if (context->mode == MODE_COMMENT_NONE) {
694 if (context->inside_node_state == STATE_INSIDE_VAL) {
695 node_t *to_be_closed = NULL;
696 if (context->content_quoted) {
697 context->content_quoted = 0;
698 to_be_closed =
699 roxml_create_node(context->pos - 1, context->src,
700 ROXML_ATTR_NODE | context->type);
701 } else {
702 to_be_closed =
703 roxml_create_node(context->pos, context->src,
704 ROXML_ATTR_NODE | context->type);
705 }
706 roxml_close_node(context->candidat_val, to_be_closed);
709 }
710 }
711 break;
712 }
713 context->pos += cur;
714 return cur;
715}
716
717ROXML_INT int _func_load_colon(roxml_parser_item_t *parser, char *chunk, void *data)
718{
719 int cur = 1;
720 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
721#ifdef DEBUG_PARSING
722 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
723#endif /* DEBUG_PARSING */
724
725 if (context->state == STATE_NODE_NAME) {
726 context->state = STATE_NODE_BEG;
727 context->candidat_node->ns = roxml_lookup_nsdef(context->namespaces, context->curr_name);
728 if (!context->candidat_node->ns) {
729 char *nsname = malloc(context->curr_name_len + 1);
730 memcpy(nsname, context->curr_name, context->curr_name_len);
731 nsname[context->curr_name_len] = '\0';
732 context->candidat_node->ns =
734 }
735 context->candidat_node->pos += context->curr_name_len + 2;
736 context->ns = 1;
737 } else if (context->state == STATE_NODE_ATTR) {
738 if (context->inside_node_state == STATE_INSIDE_ARG) {
740 if ((context->curr_name_len == 5) && (strncmp(context->curr_name, "xmlns", 5) == 0)) {
741 context->candidat_arg->type |= ROXML_NS_NODE;
742 context->nsdef = 1;
743 } else {
744 context->candidat_arg->ns = roxml_lookup_nsdef(context->namespaces, context->curr_name);
745 context->candidat_arg->pos += context->curr_name_len + 2;
746 context->ns = 1;
747 }
748
749 }
750 }
751
752 context->pos += cur;
753 return cur;
754}
755
756ROXML_INT int _func_load_default(roxml_parser_item_t *parser, char *chunk, void *data)
757{
758 int cur = 1;
759 roxml_load_ctx_t *context = (roxml_load_ctx_t *)data;
760#ifdef DEBUG_PARSING
761 fprintf(stderr, "calling func %s chunk %c\n", __func__, chunk[0]);
762#endif /* DEBUG_PARSING */
763
764 switch (context->state) {
766 context->state = context->previous_state;
767 break;
768 case STATE_NODE_BEG:
769 if (context->ns == 0) {
770 context->lvl++;
771 roxml_process_begin_node(context, context->pos - 1);
772 }
773 context->ns = 0;
774 context->state = STATE_NODE_NAME;
775 strncpy(context->curr_name, chunk, MAX_NAME_LEN);
776 while (!ROXML_WHITE(chunk[cur]) && (chunk[cur] != '>') && (chunk[cur] != '/') && (chunk[cur] != ':')
777 && (chunk[cur] != '\0')) {
778 cur++;
779 }
780 context->curr_name_len = cur;
781 break;
782 case STATE_NODE_ATTR:
783 if (context->inside_node_state == STATE_INSIDE_ARG_BEG) {
784 if (context->nsdef) {
785 if (context->namespaces == NULL) {
786 context->namespaces = context->candidat_arg;
787 context->last_ns = context->candidat_arg;
788 } else {
789 context->last_ns->next = context->candidat_arg;
790 context->last_ns = context->candidat_arg;
791 }
792 } else if (context->ns == 0) {
793 context->candidat_arg =
794 roxml_create_node(context->pos - 1, context->src, ROXML_ATTR_NODE | context->type);
795 context->candidat_arg =
796 roxml_append_node(context->candidat_node, context->candidat_arg);
797 }
798 context->ns = 0;
800 strncpy(context->curr_name, chunk, MAX_NAME_LEN);
801 while ((chunk[cur] != '=') && (chunk[cur] != '>') && (chunk[cur] != ':')
802 && (chunk[cur] != '\0')) {
803 cur++;
804 }
805 context->curr_name_len = cur;
806 if (context->nsdef) {
807 roxml_ns_t *ns = calloc(1, sizeof(roxml_ns_t) + (1 + context->curr_name_len));
808 ns->id = ROXML_NS_ID;
809 ns->alias = (char *)ns + sizeof(roxml_ns_t);
810 memcpy(ns->alias, context->curr_name, context->curr_name_len);
811 context->candidat_arg->priv = ns;
812 context->nsdef = 0;
813 if (context->candidat_node->ns) {
814 if ((context->candidat_node->ns->type & ROXML_INVALID) == ROXML_INVALID) {
815 if (strcmp(context->candidat_arg->prnt->ns->src.buf, ns->alias) == 0) {
817 context->candidat_node->ns = context->candidat_arg;
818 }
819 }
820 }
821 }
822 } else if (context->inside_node_state == STATE_INSIDE_VAL_BEG) {
823 if (context->mode != MODE_COMMENT_NONE) {
824 context->content_quoted = 1;
825 context->candidat_val =
826 roxml_create_node(context->pos + 1, context->src, ROXML_TXT_NODE | context->type);
827 } else {
828 context->candidat_val =
829 roxml_create_node(context->pos, context->src, ROXML_TXT_NODE | context->type);
830 }
831 context->candidat_val = roxml_append_node(context->candidat_arg, context->candidat_val);
833 } else if ((context->inside_node_state == STATE_INSIDE_ARG) && (chunk[0] == '=')) {
834 node_t *to_be_closed;
835
837 to_be_closed = roxml_create_node(context->pos, context->src, ROXML_ATTR_NODE | context->type);
838 roxml_close_node(context->candidat_arg, to_be_closed);
839 if ((context->curr_name_len == 5) && (strncmp(context->curr_name, "xmlns", 5) == 0)) {
840 context->nsdef = 1;
841 if (context->namespaces == NULL) {
842 context->namespaces = context->candidat_arg;
843 context->last_ns = context->candidat_arg;
844 } else {
845 context->last_ns->next = context->candidat_arg;
846 context->last_ns = context->candidat_arg;
847 }
848 }
849 }
850 break;
851 }
852
853 context->pos += cur;
854 return cur;
855}
#define ROXML_CMT_NODE
Definition roxml.h:86
#define ROXML_NSDEF_NODE
Definition roxml.h:110
#define ROXML_PI_NODE
Definition roxml.h:94
#define ROXML_INVALID_DOC
Definition roxml.h:235
#define ROXML_ATTR_NODE
Definition roxml.h:51
#define ROXML_NS_NODE
Definition roxml.h:102
#define ROXML_TXT_NODE
Definition roxml.h:78
#define ROXML_ELM_NODE
Definition roxml.h:70
#define ROXML_API
Definition roxml.h:24
#define ROXML_CDATA_NODE
Definition roxml.h:126
#define ROXML_DOCTYPE_NODE
Definition roxml.h:134
ROXML_INT void roxml_close_buff(node_t *n)
unload function
Definition roxml_buff.c:29
ROXML_INT int roxml_parse_buff(roxml_load_ctx_t *context, roxml_parser_item_t *parser, char *buffer)
generic load function
Definition roxml_buff.c:34
buffer XML document backend
ROXML_INT int roxml_is_separator(char sep)
separator tester
Definition roxml_core.c:128
ROXML_STATIC ROXML_INT void roxml_process_begin_node(roxml_load_ctx_t *context, int position)
node creation during parsing
Definition roxml_core.c:180
ROXML_INT node_t * roxml_create_node(int pos, void *src, int type)
internal function
Definition roxml_core.c:46
ROXML_STATIC ROXML_INT void roxml_close_node(node_t *n, node_t *close)
internal function
Definition roxml_core.c:65
ROXML_INT node_t * roxml_append_node(node_t *parent, node_t *n)
node append function
Definition roxml_core.c:352
ROXML_INT node_t * roxml_create_root(node_t *n)
internal function
Definition roxml_core.c:256
ROXML_STATIC ROXML_INT void roxml_set_type(node_t *n, int type)
node type setter function
Definition roxml_core.c:307
ROXML_INT node_t * roxml_set_parent(node_t *parent, node_t *n)
node parenting function
Definition roxml_core.c:313
ROXML_INT void roxml_del_tree(node_t *n)
internal function
Definition roxml_core.c:115
ROXML_STATIC ROXML_INT node_t * roxml_lookup_nsdef(node_t *nsdef, char *ns)
name space lookup in list
Definition roxml_core.c:278
ROXML_INT node_t * roxml_load(node_t *current_node, FILE *file, char *buffer)
generic load function
Definition roxml_core.c:201
ROXML_INT void roxml_free_node(node_t *n)
internal function
Definition roxml_core.c:82
ROXML_STATIC ROXML_INT void roxml_process_unaliased_ns(roxml_load_ctx_t *context)
namespace without alias name creation during parsing
Definition roxml_core.c:146
ROXML_API void roxml_close(node_t *n)
unload function
Definition roxml_core.c:25
XML parsing core module.
#define STATE_NODE_BEG
#define STATE_NODE_CDATA
#define STATE_NODE_SINGLE
#define ROXML_INVALID
#define STATE_NODE_NAME
#define STATE_NODE_COMMENT
#define MODE_COMMENT_DQUOTE
#define MODE_COMMENT_QUOTE
#define STATE_INSIDE_ARG
#define STATE_INSIDE_VAL
#define ROXML_WHITE(n)
#define STATE_NODE_END
#define STATE_NODE_CONTENT
#define STATE_NODE_ATTR
#define ROXML_FILE
#define STATE_INSIDE_VAL_BEG
#define ROXML_PENDING
#define MODE_COMMENT_NONE
#define STATE_NODE_PI
#define STATE_INSIDE_ARG_BEG
#define MAX_NAME_LEN
ROXML_INT int roxml_parse_file(roxml_load_ctx_t *context, roxml_parser_item_t *parser, FILE *file)
generic load function
Definition roxml_file.c:33
ROXML_INT void roxml_close_file(node_t *root)
unload function
Definition roxml_file.c:28
File XML document backend.
ROXML_INT roxml_parser_item_t * roxml_parser_prepare(roxml_parser_item_t *parser)
parser preparation function
ROXML_INT roxml_parser_item_t * roxml_append_parser_item(roxml_parser_item_t *parser, char *key, roxml_parse_func func)
parser item creation function
ROXML_INT void roxml_parser_free(roxml_parser_item_t *parser)
parser table deletion
Parsing engine.
node_t structure
struct node * prnt
roxml_pos_t pos
unsigned short type
struct node * ns
roxml_pos_t end
void * priv
void * src
struct node * chld
struct node * next
struct node * attr
struct node * sibl
xml parsing context
node_t * current_node
char curr_name[MAX_NAME_LEN+1]
node_t * namespaces
node_t * candidat_txt
node_t * candidat_node
node_t * candidat_val
node_t * candidat_arg
namespace structure
unsigned char id
char * alias
the parser item struct
xpath token structure
struct _xpath_tok * next
xpath token structure
Definition roxml_types.h:93
unsigned char ids[256]
Definition roxml_types.h:95
unsigned char id
Definition roxml_types.h:94
struct _xpath_tok * next
Definition roxml_types.h:97