<libroxml  version="3.0.2" />
contact: tristan.lelong@libroxml.net
roxml_edit.c
Go to the documentation of this file.
1 
12 #include <string.h>
13 #include <stdlib.h>
14 #include "roxml_core.h"
15 #include "roxml_mem.h"
16 
26 ROXML_STATIC ROXML_INT node_t *roxml_get_real_prev_sibling(node_t *n)
27 {
28  node_t *current = n->prnt->chld;
29  node_t *prev = NULL;
30 
31  while (current != n) {
32  prev = current;
33  current = current->sibl;
34  }
35 
36  return prev;
37 }
38 
48 ROXML_STATIC ROXML_INT void roxml_reset_ns(node_t *n, node_t *ns)
49 {
50  node_t *attr = NULL;
51  node_t *chld = NULL;
52 
53  if (!n)
54  return;
55 
56  if (n->ns == ns) {
57  if (n->prnt)
58  n->ns = n->prnt->ns;
59  else
60  n->ns = NULL;
61  }
62 
63  chld = n->chld;
64  while (chld) {
65  roxml_reset_ns(chld, ns);
66  chld = chld->sibl;
67  }
68 
69  attr = n->attr;
70  while (attr) {
71  if ((attr->type & ROXML_NS_NODE) == 0)
72  if (attr->ns == ns)
73  attr->ns = attr->prnt->ns;
74  attr = attr->sibl;
75  }
76 }
77 
85 ROXML_STATIC ROXML_INT void roxml_del_std_node(node_t *n)
86 {
87  node_t *current = n->prnt->chld;
88 
89  if (n->prnt && n->prnt->next == n)
90  n->prnt->next = roxml_get_real_prev_sibling(n);
91 
92  if (current == n) {
93  n->prnt->chld = n->sibl;
94  } else if (current) {
95  while (current->sibl && current->sibl != n)
96  current = current->sibl;
97  current->sibl = n->sibl;
98  }
99  roxml_del_tree(n->chld);
100  roxml_del_tree(n->attr);
101 }
102 
110 ROXML_STATIC ROXML_INT void roxml_del_txt_node(node_t *n)
111 {
112  node_t *current = n->prnt->chld;
113 
114  while (current && (current->type & ROXML_TXT_NODE) == 0)
115  current = current->sibl;
116 
117  roxml_del_std_node(current);
118 }
119 
127 ROXML_STATIC ROXML_INT void roxml_del_arg_node(node_t *n)
128 {
129  node_t *current = n->prnt->attr;
130 
131  if (n->type & ROXML_NS_NODE)
132  roxml_reset_ns(n->prnt, n);
133 
134  if (current == n) {
135  n->prnt->attr = n->sibl;
136  } else if (current) {
137  while (current->sibl && current->sibl != n)
138  current = current->sibl;
139  current->sibl = n->sibl;
140  }
141  roxml_del_tree(n->chld);
142 }
143 
144 ROXML_STATIC ROXML_INT node_t *roxml_prepend_node(node_t *parent, node_t *n)
145 {
146  if (n->type & ROXML_ATTR_NODE) {
147  n->sibl = parent->attr;
148  parent->attr = n;
149  } else {
150  n->sibl = parent->chld;
151  parent->chld = n;
152  }
153  return n;
154 }
155 
165 ROXML_STATIC ROXML_INT node_t *roxml_parent_node(node_t *parent, node_t *n, int position)
166 {
167  int nb;
168 
169  if (n == NULL)
170  return NULL;
171  if (parent == NULL)
172  return n;
173 
174  if (n->type & ROXML_ATTR_NODE)
175  nb = roxml_get_attr_nb(parent);
176  else
177  nb = roxml_get_nodes_nb(parent,
180 
181  roxml_set_parent(parent, n);
182 
183  if ((position == 0) || (position > nb)) {
184  return roxml_append_node(parent, n);
185  } else if (position == 1) {
186  return roxml_prepend_node(parent, n);
187  } else {
188  int i;
189  node_t *prev = parent->chld;
190  node_t *next = parent->chld;
191 
192  if (n->type & ROXML_ATTR_NODE)
193  next = parent->attr;
194  for (i = 1; i < position; i++) {
195  prev = next;
196  next = next->sibl;
197  }
198  n->sibl = next;
199  prev->sibl = n;
200  }
201  return n;
202 }
203 
205 {
206  if (n == ROXML_INVALID_DOC)
207  return;
208 
209  if ((n->type & ROXML_ELM_NODE) ||
210  (n->type & ROXML_DOCTYPE_NODE) || (n->type & ROXML_PI_NODE) || (n->type & ROXML_CMT_NODE)) {
212  } else if (n->type & ROXML_ATTR_NODE) {
214  } else if (n->type & ROXML_TXT_NODE) {
216  }
217  roxml_free_node(n);
218 }
219 
220 ROXML_STATIC ROXML_INT void roxml_generate_cmt_node(node_t *n, char *content)
221 {
222  int content_l = strlen(content);
223 
224  n->src.buf = malloc(sizeof(char) * (content_l + 8));
225  sprintf(n->src.buf, "<!--%s-->", content);
226  n->end = content_l + 4;
227 }
228 
229 ROXML_STATIC ROXML_INT void roxml_generate_txt_node(node_t *n, char *content)
230 {
231  int content_l = strlen(content);
232 
233  n->src.buf = malloc(sizeof(char) * (content_l + 1));
234  sprintf(n->src.buf, "%s", content);
235  n->end = content_l + 1;
236 }
237 
238 ROXML_STATIC ROXML_INT void roxml_generate_elm_node(node_t *n, char *name, char *content)
239 {
240  int content_l = 0;
241  int name_l = strlen(name);
242 
243  if (content)
244  content_l = strlen(content);
245 
246  if (content) {
247  n->src.buf = malloc(sizeof(char) * (name_l * 2 + content_l + 6));
248  sprintf(n->src.buf, "<%s>%s</%s>", name, content, name);
249  n->end = name_l + content_l + 2;
250 
251  node_t *new_txt =
253  roxml_append_node(n, new_txt);
254  new_txt->end = name_l + content_l + 2;
255  } else {
256  n->src.buf = malloc(sizeof(char) * (name_l + 5));
257  sprintf(n->src.buf, "<%s />", name);
258  n->end = 0;
259  }
260 }
261 
262 ROXML_STATIC ROXML_INT void roxml_generate_pi_node(node_t *n, char *name, char *content)
263 {
264  int content_l = 0;
265  int name_l = strlen(name);
266 
267  if (content)
268  content_l = strlen(content);
269 
270  if (content_l) {
271  n->src.buf = malloc(sizeof(char) * (name_l + content_l + 8));
272  sprintf(n->src.buf, "<?%s %s?>", name, content);
273  n->end = name_l + content_l + 3;
274  } else {
275  n->src.buf = malloc(sizeof(char) * (name_l + 7));
276  sprintf(n->src.buf, "<?%s?>", name);
277  n->end = name_l + 2;
278  }
279 }
280 
281 ROXML_STATIC ROXML_INT void roxml_generate_attr_node(node_t *n, int type, char *name, char *content)
282 {
283  int xmlns_l = 0;
284  int content_l = strlen(content);
285  int name_l = strlen(name);
286 
287  if (type & ROXML_NS_NODE) {
288  xmlns_l = 5;
289  if (name_l > 0)
290  xmlns_l++;
291 
292  n->src.buf = malloc(sizeof(char) * (name_l + content_l + xmlns_l + 4));
293  sprintf(n->src.buf, "xmlns%s%s=\"%s\"", name_l ? ":" : "", name, content);
294 
295  roxml_ns_t *ns = calloc(1, sizeof(roxml_ns_t) + name_l + 1);
296  ns->id = ROXML_NS_ID;
297  ns->alias = (char *)ns + sizeof(roxml_ns_t);
298  if (name)
299  strcpy(ns->alias, name);
300  n->priv = ns;
301  } else {
302  n->src.buf = malloc(sizeof(char) * (name_l + content_l + 4));
303  sprintf(n->src.buf, "%s=\"%s\"", name, content);
304  }
305 
306  node_t *new_txt =
307  roxml_create_node(name_l + 2 + xmlns_l, n->src.buf, ROXML_TXT_NODE | ROXML_PENDING | ROXML_BUFF);
308  new_txt->end = name_l + content_l + 2 + xmlns_l;
309  n->end = name_l + 1 + xmlns_l;
310  roxml_append_node(n, new_txt);
311 }
312 
313 ROXML_INT int roxml_add_node_check(node_t *parent, int type, char *name, char *content)
314 {
315  int valid = 1;
316 
317  if (parent) {
318  if (parent->type & ROXML_ATTR_NODE) {
319  if (((type & ROXML_TXT_NODE) == 0) || (parent->chld))
320  valid = 0;
321  } else if ((parent->type & ROXML_ELM_NODE) == 0) {
322  if (parent->prnt && (parent->prnt->type & ROXML_ELM_NODE))
323  valid = 2;
324  else
325  valid = 0;
326  }
327  }
328 
329  switch (type & ~ROXML_ESCAPED_MOD) {
331  case ROXML_ATTR_NODE:
332  if (!name || !content)
333  valid = 0;
334  break;
335  case ROXML_TXT_NODE:
336  case ROXML_CMT_NODE:
337  case ROXML_CDATA_NODE:
338  if (!content)
339  valid = 0;
340  break;
341  case ROXML_ELM_NODE:
342  case ROXML_PI_NODE:
343  if (!name)
344  valid = 0;
345  break;
346  default:
347  valid = 0;
348  }
349 
350  return valid;
351 }
352 
353 ROXML_API node_t *roxml_add_node(node_t *parent, int position, int type, char *name, char *content)
354 {
355  int ret;
356  node_t *new_node = NULL;
357 
358  if (content && (type & ROXML_ESCAPED_MOD) && !(type & ROXML_NON_ESCAPABLE_NODES)) {
359  int size = roxml_escape(content, ENCODE, NULL);
360  char *out = malloc(size + 1);
361  roxml_escape(content, ENCODE, out);
362  content = out;
363  }
364 
365  ret = roxml_add_node_check(parent, type, name, content);
366  if (ret == 0)
367  return NULL;
368  else if (ret == 2)
369  parent = parent->prnt;
370 
371  if (parent == NULL) {
373  parent = roxml_create_root(n);
374  }
375 
376  new_node = roxml_create_node(0, NULL, type | ROXML_PENDING | ROXML_BUFF);
377 
378  if (type & ROXML_ATTR_NODE)
379  roxml_generate_attr_node(new_node, type, name, content);
380  else if (type & ROXML_CMT_NODE)
381  roxml_generate_cmt_node(new_node, content);
382  else if (type & ROXML_PI_NODE)
383  roxml_generate_pi_node(new_node, name, content);
384  else if (type & ROXML_TXT_NODE)
385  roxml_generate_txt_node(new_node, content);
386  else if (type & ROXML_ELM_NODE)
387  roxml_generate_elm_node(new_node, name, content);
388 
389  if (((type & ROXML_NON_ESCAPABLE_NODES) == 0) && (type & ROXML_ESCAPED_MOD))
390  free(content);
391 
392  return roxml_parent_node(parent, new_node, position);
393 }
394 
396 {
397  node_t *attr = NULL;
398  node_t *chld = NULL;
399 
400  if (n == ROXML_INVALID_DOC)
401  return ROXML_INVALID_DOC;
402 
403  if (ns) {
404  node_t *common_parent = n;
405  while (common_parent && common_parent != ns->prnt)
406  common_parent = common_parent->prnt;
407  if (common_parent != ns->prnt)
408  return NULL;
409  }
410 
411  n->ns = ns;
412  chld = n->chld;
413  while (chld) {
414  roxml_set_ns(chld, ns);
415  chld = chld->sibl;
416  }
417 
418  attr = n->attr;
419  while (attr) {
420  if ((attr->type & ROXML_NS_NODE) == 0)
421  attr->ns = ns;
422  attr = attr->sibl;
423  }
424 
425  return n;
426 }
#define ROXML_INVALID_DOC
Definition: roxml.h:235
#define ROXML_NS_NODE
Definition: roxml.h:102
node_t structure
Definition: roxml_types.h:133
ROXML_API int roxml_get_nodes_nb(node_t *n, int type)
number of nodes getter function
struct node * attr
Definition: roxml_types.h:145
#define ROXML_NON_ESCAPABLE_NODES
Definition: roxml.h:174
#define ROXML_ATTR_NODE
Definition: roxml.h:51
#define ROXML_PENDING
roxml_pos_t end
Definition: roxml_types.h:141
unsigned char id
Definition: roxml_types.h:120
ROXML_STATIC ROXML_INT node_t * roxml_get_real_prev_sibling(node_t *n)
get real sibling
Definition: roxml_edit.c:26
ROXML_STATIC ROXML_INT void roxml_del_std_node(node_t *n)
node deletion function
Definition: roxml_edit.c:85
#define ROXML_PI_NODE
Definition: roxml.h:94
struct node * chld
Definition: roxml_types.h:143
ROXML_INT node_t * roxml_create_root(node_t *n)
internal function
Definition: roxml_core.c:251
char * alias
Definition: roxml_types.h:122
#define ROXML_ESCAPED_MOD
Definition: roxml.h:166
ROXML_INT void roxml_free_node(node_t *n)
internal function
Definition: roxml_core.c:82
#define ROXML_API
Definition: roxml.h:24
#define ROXML_DOCTYPE_NODE
Definition: roxml.h:134
ROXML_API int roxml_escape(const char *buf, int decode, char *out)
XML encoding/decoding function.
Definition: roxml_content.c:31
struct node * sibl
Definition: roxml_types.h:142
#define ROXML_CMT_NODE
Definition: roxml.h:86
void * src
Definition: roxml_types.h:138
ROXML_API void roxml_del_node(node_t *n)
node deletion function
Definition: roxml_edit.c:204
ROXML_STATIC ROXML_INT void roxml_reset_ns(node_t *n, node_t *ns)
internal function
Definition: roxml_edit.c:48
ROXML_INT node_t * roxml_set_parent(node_t *parent, node_t *n)
node parenting function
Definition: roxml_core.c:308
struct node * ns
Definition: roxml_types.h:147
XML parsing core module.
namespace structure
Definition: roxml_types.h:119
ROXML_API node_t * roxml_add_node(node_t *parent, int position, int type, char *name, char *content)
add a node to the tree
Definition: roxml_edit.c:353
#define ROXML_ELM_NODE
Definition: roxml.h:70
XML internal memory management module.
void * priv
Definition: roxml_types.h:148
ROXML_INT node_t * roxml_create_node(int pos, void *src, int type)
internal function
Definition: roxml_core.c:46
struct node * prnt
Definition: roxml_types.h:144
#define ROXML_BUFF
#define ROXML_TXT_NODE
Definition: roxml.h:78
unsigned short type
Definition: roxml_types.h:134
ROXML_STATIC ROXML_INT node_t * roxml_parent_node(node_t *parent, node_t *n, int position)
node relocate function
Definition: roxml_edit.c:165
#define ENCODE
Definition: roxml.h:182
ROXML_INT node_t * roxml_append_node(node_t *parent, node_t *n)
node append function
Definition: roxml_core.c:347
ROXML_API node_t * roxml_set_ns(node_t *n, node_t *ns)
namespace setter function
Definition: roxml_edit.c:395
ROXML_API int roxml_get_attr_nb(node_t *n)
number of attribute getter function
ROXML_STATIC ROXML_INT void roxml_del_arg_node(node_t *n)
attribute node deletion function
Definition: roxml_edit.c:127
ROXML_STATIC ROXML_INT void roxml_del_txt_node(node_t *n)
text node deletion function
Definition: roxml_edit.c:110
ROXML_INT void roxml_del_tree(node_t *n)
internal function
Definition: roxml_core.c:115
#define ROXML_CDATA_NODE
Definition: roxml.h:126