<libroxml  version="2.2.1" />
contact: tristan.lelong@libroxml.net
roxml.c
Go to the documentation of this file.
1 
25 #include "roxml-internal.h"
26 
27 void ROXML_API roxml_release(void * data)
28 {
29  memory_cell_t *ptr = &head_cell;
30  memory_cell_t *to_delete = NULL;
31 
32  if(data == RELEASE_LAST) {
33  while((ptr->prev != NULL)&&(ptr->prev->id != pthread_self())) { ptr = ptr->prev; }
34  if(ptr->prev == NULL) { return; }
35 
36  to_delete = ptr->prev;
37 
38  if(to_delete->next) {
39  to_delete->prev->next = to_delete->next;
40  to_delete->next->prev = to_delete->prev;
41  } else {
42  if(to_delete->prev != &head_cell) {
43  head_cell.prev = to_delete->prev;
44  } else {
45  head_cell.prev = NULL;
46  }
47  to_delete->prev->next = NULL;
48  }
49 
50  if(PTR_IS_STAR(to_delete)) {
51  int i = 0;
52  for(i = 0; i < to_delete->occ; i++) { free(((void**)(to_delete->ptr))[i]); }
53  }
54  if(to_delete->type != PTR_NONE) {
55  free(to_delete->ptr);
56  to_delete->type = PTR_NONE;
57  free(to_delete);
58  }
59  } else if(data == RELEASE_ALL) {
60  head_cell.prev = NULL;
61  while((head_cell.next != NULL)) {
62  to_delete = head_cell.next;
63  if(to_delete->next) { to_delete->next->prev = &head_cell; }
64  head_cell.next = to_delete->next;
65 
66  if(PTR_IS_STAR(to_delete)) {
67  int i = 0;
68  for(i = 0; i < to_delete->occ; i++) { free(((void**)(to_delete->ptr))[i]); }
69  }
70  free(to_delete->ptr);
71  to_delete->ptr = NULL;
72  to_delete->type = PTR_NONE;
73  free(to_delete);
74  }
75  } else {
76  while((ptr->next != NULL)&&(ptr->next->ptr != data)) { ptr = ptr->next; }
77  if(ptr->next == NULL) {
78  return;
79  }
80 
81  to_delete = ptr->next;
82  if(to_delete->next) {
83  to_delete->next->prev = ptr;
84  } else {
85  if(ptr == &head_cell) {
86  head_cell.prev = NULL;
87  } else {
88  head_cell.prev = to_delete->prev;
89  }
90  }
91  ptr->next = to_delete->next;
92  if(PTR_IS_STAR(to_delete)) {
93  int i = 0;
94  for(i = 0; i < to_delete->occ; i++) { free(((void**)(to_delete->ptr))[i]); }
95  }
96  free(to_delete->ptr);
97  to_delete->type = PTR_NONE;
98  free(to_delete);
99  }
100  if(head_cell.next == &head_cell) { head_cell.next = NULL; }
101  if(head_cell.prev == &head_cell) { head_cell.prev = NULL; }
102 }
103 
104 char * ROXML_API roxml_get_content(node_t *n, char * buffer, int bufsize, int *size)
105 {
106  int total = 0;
107  char * content = buffer;
108 
109  if(n == NULL) {
110  if(size) {
111  *size = 0;
112  }
113  if(buffer) {
114  strcpy(buffer, "");
115  return buffer;
116  }
117  return NULL;
118  } else if(n->type & ROXML_ELM_NODE) {
119  node_t *ptr = n->chld;
120  while(ptr) {
121  if((ptr->type & ROXML_NODE_TYPES) == ROXML_TXT_NODE) {
122  total += ptr->end - ptr->pos;
123  }
124  ptr = ptr->sibl;
125  }
126 
127  if(content == NULL) {
128  content = roxml_malloc(sizeof(char), total+1, PTR_CHAR);
129  bufsize = total+1;
130  }
131  if(content == NULL) { return NULL; }
132 
133  total = 0;
134  ptr = n->chld;
135  while(ptr) {
136  if((ptr->type & ROXML_NODE_TYPES) == ROXML_TXT_NODE) {
137  int ret_len = 0;
138  int read_size = ptr->end - ptr->pos;
139 
140  if(total+read_size > bufsize-1) {
141  read_size = bufsize - total - 1;
142  }
143  ret_len += roxml_read(ptr->pos, read_size, content+total, ptr);
144 
145  total += ret_len;
146  }
147  ptr = ptr->sibl;
148  }
149  } else {
150  node_t *target = n;
151  char name[ROXML_BASE_LEN];
152  int read_size = 0;
153  int name_len = 0;
154  int spec_offset = 0;
155 
156  roxml_get_name(n, name, ROXML_BASE_LEN);
157  name_len = strlen(name);
158 
159  if(n->type & ROXML_DOCTYPE_NODE) {
160  total = target->end - target->pos - name_len - 2;
161  spec_offset = target->pos + name_len + 2;
162  } else if(n->type & ROXML_TXT_NODE) {
163  total = target->end - target->pos;
164  spec_offset = target->pos;
165  } else if(n->type & ROXML_CMT_NODE) {
166  total = target->end - target->pos - 4;
167  spec_offset = target->pos + 4;
168  } else if(n->type & ROXML_PI_NODE) {
169  total = target->end - target->pos - name_len - 3;
170  spec_offset = target->pos + name_len + 3;
171  } else if(n->type & ROXML_ATTR_NODE) {
172  target = n->chld;
173  if(target) {
174  spec_offset = target->pos;
175  total = target->end - target->pos;
176  } else {
177  spec_offset = 0;
178  total = 0;
179  }
180  }
181 
182  if(content == NULL) {
183  content = roxml_malloc(sizeof(char), total+1, PTR_CHAR);
184  bufsize = total+1;
185  }
186  if(content == NULL) { return NULL; }
187 
188  read_size = total;
189  if(read_size > bufsize-1) {
190  read_size = bufsize-1;
191  }
192  total = roxml_read(spec_offset, read_size, content, target);
193  }
194 
195  content[total] = '\0';
196  if(size) {
197  *size = total+1;
198  }
199  return content;
200 }
201 
202 char * ROXML_API roxml_get_name(node_t *n, char * buffer, int size)
203 {
204  int offset = 0;
205  int count = 0;
206  char tmp_name[INTERNAL_BUF_SIZE];
207 
208  memset(tmp_name, 0, INTERNAL_BUF_SIZE*sizeof(char));
209 
210  if(buffer) {
211  memset(buffer, 0, size*sizeof(char));
212  }
213 
214  if(n == NULL) {
215  if(buffer) {
216  strcpy(buffer, "");
217  }
218  return buffer;
219  }
220 
221  if(n->prnt == NULL) {
222  strcpy(tmp_name, "documentRoot");
223  } else if(n->type & ROXML_NS_NODE) {
224  roxml_ns_t * ns = (roxml_ns_t*)n->priv;
225  if(ns) {
226  strcpy(tmp_name, ns->alias);
227  } else {
228  tmp_name[0] ='\0';
229  }
230  } else if((n->type & ROXML_TXT_NODE) ||
231  (n->type & ROXML_CMT_NODE))
232  {
233  if(buffer) {
234  strcpy(buffer, "");
235  return buffer;
236  }
237  return NULL;
238  } else {
239  int spec_offset = 0;
240  if(n->type & ROXML_PI_NODE) {
241  spec_offset = 2;
242  } else if(n->type & ROXML_DOCTYPE_NODE) {
243  spec_offset = 1;
244  }
245 
246  roxml_read(n->pos+spec_offset, INTERNAL_BUF_SIZE, tmp_name, n);
247  while(ROXML_WHITE(tmp_name[offset]) || tmp_name[offset] == '<') {
248  offset++;
249  }
250  count = offset;
251 
252  if(n->type & ROXML_PI_NODE) {
253  for(;count < INTERNAL_BUF_SIZE; count++) {
254  if(ROXML_WHITE(tmp_name[count])) {
255  break;
256  } else if((tmp_name[count] == '?')&&(tmp_name[count+1] == '>')) {
257  break;
258  }
259  }
260  } else if(n->type & ROXML_ELM_NODE) {
261  for(;count < INTERNAL_BUF_SIZE; count++) {
262  if(ROXML_WHITE(tmp_name[count])) {
263  break;
264  } else if((tmp_name[count] == '/')&&(tmp_name[count+1] == '>')) {
265  break;
266  } else if(tmp_name[count] == '>') {
267  break;
268  }
269  }
270  } else if(n->type & ROXML_ATTR_NODE) {
271  for(;count < INTERNAL_BUF_SIZE; count++) {
272  if(ROXML_WHITE(tmp_name[count])) {
273  break;
274  } else if(tmp_name[count] == '=') {
275  break;
276  } else if(tmp_name[count] == '>') {
277  break;
278  } else if((tmp_name[count] == '/')&&(tmp_name[count+1] == '>')) {
279  break;
280  }
281  }
282  } else if(n->type & ROXML_DOCTYPE_NODE) {
283  for(;count < INTERNAL_BUF_SIZE; count++) {
284  if(ROXML_WHITE(tmp_name[count])) {
285  break;
286  } else if(tmp_name[count] == '>') {
287  break;
288  }
289  }
290  }
291  tmp_name[count] = '\0';
292  }
293 
294  if(buffer == NULL) {
295  buffer = (char*)roxml_malloc(sizeof(char), strlen(tmp_name)-offset+1, PTR_CHAR);
296  strcpy(buffer, tmp_name+offset);
297  } else {
298  if(strlen(tmp_name)-offset < (unsigned int)size) {
299  size = strlen(tmp_name)-offset;
300  }
301  strncpy(buffer, tmp_name+offset, size);
302  }
303  return buffer;
304 }
305 
307 {
308  node_t *root = n;
309  if(root == NULL) {
310  return;
311  }
312  while(root->prnt != NULL) {
313  root = root->prnt;
314  }
315 
316  roxml_del_tree(root->chld);
317  roxml_del_tree(root->sibl);
318  if((root->type & ROXML_FILE) == ROXML_FILE) {
319  fclose(root->src.fil);
320  }
321  roxml_free_node(root);
322 }
323 
325 {
326  node_t *ptr = n;
327  int nb = -1;
328  if(n) {
329  nb = 0;
330  if(ptr->chld) {
331  ptr = ptr->chld;
332  do {
333  if(ptr->type & type) {
334  nb++;
335  }
336  ptr = ptr->sibl;
337  } while(ptr);
338  }
339  if(type & ROXML_ATTR_NODE) {
340  ptr = n->attr;
341  while(ptr) {
342  nb++;
343  ptr = ptr->sibl;
344  }
345  }
346  }
347  return nb;
348 }
349 
350 node_t * ROXML_API roxml_get_nodes(node_t *n, int type, char * name, int nth)
351 {
352  node_t *ptr = NULL;
353 
354  if(n == NULL) {
355  return NULL;
356  }
357 
358  if(name == NULL) {
359  int count = 0;
360  if(n->ns && (type & ROXML_NS_NODE)) {
361  ptr = n->ns;
362  if(nth == 0) {
363  return ptr;
364  }
365  } else if(n->attr && (type & ROXML_ATTR_NODE)) {
366  ptr = n->attr;
367  if(nth == 0) {
368  return ptr;
369  }
370  while((ptr->sibl)&&(nth > count)) {
371  ptr = ptr->sibl;
372  count++;
373  }
374  } else {
375  ptr = n->chld;
376  while(ptr && !((ptr->type & ROXML_NODE_TYPES) & type)) {
377  ptr = ptr->sibl;
378  }
379  }
380  if(nth > count) {
381  ptr = n->chld;
382  while(ptr && !((ptr->type & ROXML_NODE_TYPES) & type)) {
383  ptr = ptr->sibl;
384  }
385  while(ptr && (ptr->sibl) && (nth > count)) {
386  ptr = ptr->sibl;
387  if((ptr->type & ROXML_NODE_TYPES) & type) {
388  count++;
389  }
390  }
391  }
392  if(nth > count) { return NULL; }
393  } else {
394  if(n->attr && (type & ROXML_ATTR_NODE)) {
395  ptr = n->attr;
396  while(ptr) {
397  int ans = strcmp(roxml_get_name(ptr, NULL, 0), name);
399  if(ans == 0) {
400  return ptr;
401  }
402  ptr = ptr->sibl;
403  }
404  }
405  ptr = n->chld;
406  while(ptr) {
407  if((ptr->type & ROXML_NODE_TYPES) & type) {
408  int ans = strcmp(roxml_get_name(ptr, NULL, 0), name);
410  if(ans == 0) {
411  return ptr;
412  }
413  }
414  ptr = ptr->sibl;
415  }
416  }
417  return ptr;
418 }
419 
421 {
422  node_t * attr = NULL;
423  node_t * chld = NULL;
424 
425  if(!n) {
426  return NULL;
427  }
428 
429  if(ns) {
430  node_t * common_parent = n;
431  while(common_parent && common_parent != ns->prnt) {
432  common_parent = common_parent->prnt;
433  }
434  if(common_parent != ns->prnt) {
435  return NULL;
436  }
437  }
438 
439  n->ns = ns;
440  chld = n->chld;
441  while(chld) {
442  roxml_set_ns(chld, ns);
443  chld = chld->sibl;
444  }
445 
446  attr = n->attr;
447  while(attr) {
448  if((attr->type & ROXML_NS_NODE) == 0) {
449  attr->ns = ns;
450  }
451  attr = attr->sibl;
452  }
453 
454  return n;
455 }
456 
458 {
459  return roxml_get_nodes(n, ROXML_NS_NODE, NULL, 0);
460 }
461 
463 {
465 }
466 
468 {
469  return roxml_get_nodes(n, ROXML_PI_NODE, NULL, nth);
470 }
471 
473 {
475 }
476 
478 {
479  return roxml_get_nodes(n, ROXML_CMT_NODE, NULL, nth);
480 }
481 
483 {
485 }
486 
488 {
489  return roxml_get_nodes(n, ROXML_TXT_NODE, NULL, nth);
490 }
491 
493 {
495 }
496 
497 node_t * ROXML_API roxml_get_attr(node_t *n, char * name, int nth)
498 {
499  return roxml_get_nodes(n, ROXML_ATTR_NODE, name, nth);
500 }
501 
503 {
505 }
506 
507 node_t * ROXML_API roxml_get_chld(node_t *n, char * name, int nth)
508 {
509  return roxml_get_nodes(n, ROXML_ELM_NODE, name, nth);
510 }
511 
513 {
514  node_t * prev = NULL;
515  node_t * prev_elm = NULL;
516 
517  if(n && n->prnt) {
518  prev = n->prnt->chld;
519  while(prev && prev != n) {
520  if((prev->type & ROXML_NODE_TYPES) == ROXML_ELM_NODE) {
521  prev_elm = prev;
522  }
523  prev = prev->sibl;
524  }
525  }
526  return prev_elm;
527 }
528 
530 {
531  if(n) {
532  while(n->sibl && (n->sibl->type & ROXML_NODE_TYPES) != ROXML_ELM_NODE) {
533  n = n->sibl;
534  }
535  return n->sibl;
536  }
537  return NULL;
538 }
539 
541 {
542  if(n) {
543  if(n->prnt == NULL) {
544  return n;
545  } else {
546  return n->prnt;
547  }
548  }
549  return NULL;
550 }
551 
553 {
554  node_t * root = NULL;
555  if(n) {
556  root = n;
557 
558  while(root->prnt) root = root->prnt;
559 
560  if(root->chld && (root->chld->type & ROXML_NODE_TYPES) == ROXML_PI_NODE) {
561  int lone_elm = 0;
562  char root_name[16];
563  node_t * lone_elm_node = 0;
564  if(strcmp(roxml_get_name(root->chld, root_name, 16), "xml") == 0) {
565  if(root->chld->sibl) {
566  node_t * ptr = root->chld->sibl;
567  while(ptr) {
568  if(ptr->type & ROXML_ELM_NODE) {
569  lone_elm_node = ptr;
570  lone_elm++;
571  }
572  ptr = ptr->sibl;
573  }
574  }
575  }
576  if(lone_elm == 1) {
577  root = lone_elm_node;
578  }
579  }
580  }
581  return root;
582 }
583 
585 {
586  if(n) {
587  return (n->type & ROXML_NODE_TYPES);
588  }
589  return 0;
590 }
591 
593 {
594  int idx = 1;
595  char name[256];
596  node_t * prnt;
597  node_t * first;
598 
599  if(n == NULL) { return 0; }
600 
601  roxml_get_name(n, name, 256);
602 
603  prnt = n->prnt;
604  if(!prnt) {
605  return 1;
606  }
607  first = prnt->chld;
608 
609  while((first)&&(first != n)) {
610  char twin[256];
611  roxml_get_name(first, twin, 256);
612  if(strcmp(name, twin) == 0) { idx++; }
613  first = first->sibl;
614  }
615 
616  return idx;
617 }
618 
620 {
621  FILE * file = NULL;
622  node_t *current_node = NULL;
623  if(fd < 0) {
624  return NULL;
625  }
626  file = fdopen(fd, "r");
627  if(file == NULL) {
628  return NULL;
629  }
630  current_node = roxml_create_node(0, file, ROXML_ELM_NODE | ROXML_FILE);
631  current_node = roxml_append_node(NULL, current_node);
632  return roxml_load(current_node, file, NULL);
633 }
634 
635 node_t * ROXML_API roxml_load_doc(char *filename)
636 {
637  node_t *current_node = NULL;
638  FILE* file = fopen(filename, "rb");
639  if(file == NULL) {
640  return NULL;
641  }
642  current_node = roxml_create_node(0, file, ROXML_ELM_NODE | ROXML_FILE);
643  current_node = roxml_append_node(NULL, current_node);
644  return roxml_load(current_node, file, NULL);
645 }
646 
648 {
649  node_t *current_node = NULL;
650  if(buffer == NULL) { return NULL; }
651  current_node = roxml_create_node(0, buffer, ROXML_ELM_NODE | ROXML_BUFF);
652  current_node = roxml_append_node(NULL, current_node);
653  return roxml_load(current_node, NULL, buffer);
654 }
655 
656 node_t ** ROXML_API roxml_xpath(node_t *n, char * path, int *nb_ans)
657 {
658  int index = 0;
659  int count = 0;
660  xpath_node_t * xpath = NULL;
661  node_t ** node_set = NULL;
662  node_t * root = n;
663  char * full_path_to_find;
664  char * path_to_find;
665 
666  if(n == NULL) {
667  if(nb_ans) { *nb_ans = 0; }
668  return NULL;
669  }
670 
671  root = roxml_get_root(n);
672 
673  full_path_to_find = strdup(path);
674  path_to_find = full_path_to_find;
675 
676  index = roxml_parse_xpath(path_to_find, &xpath, 0);
677 
678  if(index >= 0) {
679  node_set = roxml_exec_xpath(root, n, xpath, index, &count);
680 
681  roxml_free_xpath(xpath, index);
682  free(full_path_to_find);
683 
684  if(count == 0) {
685  roxml_release(node_set);
686  node_set = NULL;
687  }
688  }
689  if(nb_ans) {
690  *nb_ans = count;
691  }
692 
693  return node_set;
694 }
695 
697 {
698  if(n == NULL) return;
699 
700  if((n->type & ROXML_ELM_NODE) ||
701  (n->type & ROXML_DOCTYPE_NODE) ||
702  (n->type & ROXML_PI_NODE) ||
703  (n->type & ROXML_CMT_NODE))
704  {
706  } else if(n->type & ROXML_ATTR_NODE) {
708  } else if(n->type & ROXML_TXT_NODE) {
710  }
711  roxml_free_node(n);
712 }
713 
714 int ROXML_API roxml_commit_changes(node_t *n, char * dest, char ** buffer, int human)
715 {
716  int size = 0;
717  int len = 0;
718  FILE *fout = NULL;
719 
720  if(n) {
721  len = ROXML_LONG_LEN;
722  if(dest) {
723  fout = fopen(dest, "w");
724  }
725  if(buffer) {
726  *buffer = (char*)malloc(ROXML_LONG_LEN);
727  memset(*buffer, 0, ROXML_LONG_LEN);
728  }
729 
730  if((n->prnt == NULL)||(n->prnt && n->prnt->prnt == NULL)) {
731  if(n->prnt) {
732  n = n->prnt->chld;
733  } else {
734  n = n->chld;
735  }
736  while(n) {
737  roxml_write_node(n, fout, buffer, human, 0, &size, &len);
738  n = n->sibl;
739  }
740  } else {
741  roxml_write_node(n, fout, buffer, human, 0, &size, &len);
742  }
743 
744  if(buffer) {
745  char * ptr = NULL;
746  len -= ROXML_LONG_LEN;
747  ptr = *buffer + len;
748  len += strlen(ptr);
749  } else {
750  len = ftell(fout);
751  }
752 
753  if(fout) {
754  fclose(fout);
755  }
756  }
757 
758  return len;
759 }
760 
761 node_t * roxml_add_node(node_t * parent, int position, int type, char *name, char *value)
762 {
763  int name_l = 0;
764  int end_node = 0;
765  int content_l = 0;
766  int content_pos = 0;
767  int end_content = 0;
768  char * buffer = NULL;
769  node_t * new_node;
770 
771  int allow_attrib_child;
772 
773  if(parent) {
774  if(parent->type & ROXML_ATTR_NODE) {
775  if(((type & ROXML_TXT_NODE) == 0)||(parent->chld)) {
776  return NULL;
777  }
778  } else if((parent->type & ROXML_ELM_NODE) == 0) {
779  if(parent->prnt && (parent->prnt->type & ROXML_ELM_NODE)) {
780  parent = parent->prnt;
781  } else {
782  return NULL;
783  }
784  }
785  }
786 
787  if(value) {
788  content_l = strlen(value);
789  }
790  if(name) {
791  name_l = strlen(name);
792  }
793 
794  if(type & ROXML_ATTR_NODE) {
795  int xmlns_l = 0;
796  if(!name || !value) { return NULL; }
797  if(type & ROXML_NS_NODE) {
798  if(name_l > 0) {
799  xmlns_l = 6;
800  } else {
801  xmlns_l = 5;
802  }
803  buffer = (char*)malloc(sizeof(char)*(name_l+content_l+xmlns_l+4));
804  sprintf(buffer,"xmlns%s%s=\"%s\"", name_l?":":"", name, value);
805  } else {
806  buffer = (char*)malloc(sizeof(char)*(name_l+content_l+4));
807  sprintf(buffer,"%s=\"%s\"",name, value);
808  }
809  content_pos = name_l + 2 + xmlns_l;
810  end_node = name_l + 1 + xmlns_l;
811  end_content = name_l + content_l + 2 + xmlns_l;
812  } else if(type & ROXML_CMT_NODE) {
813  if(!value) { return NULL; }
814  buffer = (char*)malloc(sizeof(char)*(content_l+8));
815  sprintf(buffer,"<!--%s-->", value);
816  content_pos = 0;
817  end_node = content_l + 4;
818  end_content = content_l + 4;
819  } else if(type & ROXML_PI_NODE) {
820  if(!name) { return NULL; }
821  if(content_l) {
822  buffer = (char*)malloc(sizeof(char)*(name_l+content_l+8));
823  sprintf(buffer,"<?%s %s?>", name, value);
824  end_node = name_l + content_l + 3;
825  end_content = name_l + content_l + 5;
826  } else {
827  buffer = (char*)malloc(sizeof(char)*(name_l+7));
828  sprintf(buffer,"<?%s?>", name);
829  end_node = name_l + 2;
830  end_content = name_l + 4;
831  }
832  content_pos = 0;
833  } else if(type & ROXML_TXT_NODE) {
834  if(!value) { return NULL; }
835  buffer = (char*)malloc(sizeof(char)*(content_l+1));
836  sprintf(buffer,"%s", value);
837  content_pos = 0;
838  end_node = content_l + 1;
839  end_content = content_l + 1;
840  } else if(type & ROXML_ELM_NODE) {
841  if(!name) { return NULL; }
842  if(value) {
843  buffer = (char*)malloc(sizeof(char)*(name_l*2+content_l+6));
844  sprintf(buffer,"<%s>%s</%s>",name, value, name);
845  content_pos = name_l+2;
846  end_node = name_l + content_l + 2;
847  end_content = end_node;
848  } else {
849  buffer = (char*)malloc(sizeof(char)*(name_l+5));
850  sprintf(buffer,"<%s />",name);
851  }
852  } else {
853  return NULL;
854  }
855 
856  new_node = roxml_create_node(0, buffer, type | ROXML_PENDING | ROXML_BUFF);
857  new_node->end = end_node;
858 
859  if(type & ROXML_NS_NODE) {
860  roxml_ns_t * ns = calloc(1, sizeof(roxml_ns_t) + name_l + 1);
861  ns->id = ROXML_NS_ID;
862  ns->alias = (char*)ns + sizeof(roxml_ns_t);
863  strcpy(ns->alias, name);
864  new_node->priv = ns;
865  }
866 
867 
868  if(((type & ROXML_ELM_NODE) && content_l) || (type & ROXML_ATTR_NODE)) {
869  node_t *new_txt = roxml_create_node(content_pos, buffer, ROXML_TXT_NODE | ROXML_PENDING | ROXML_BUFF);
870  roxml_append_node(new_node, new_txt);
871  new_txt->end = end_content;
872  }
873 
874  if(parent == NULL) {
875  xpath_tok_table_t * table = (xpath_tok_table_t*)calloc(1, sizeof(xpath_tok_table_t));
876  parent = roxml_create_node(0, NULL, ROXML_ELM_NODE | ROXML_PENDING | ROXML_BUFF);
877  parent->end = 1;
878 
879  table->id = ROXML_REQTABLE_ID;
880  table->ids[ROXML_REQTABLE_ID] = 1;
881 
882  pthread_mutex_init(&table->mut, NULL);
883  parent->priv = (void*)table;
884 
885  roxml_append_node(parent, new_node);
886  } else {
887  roxml_parent_node(parent, new_node, position);
888  }
889  return new_node;
890 }
891