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