<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
26ROXML_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
48ROXML_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
85ROXML_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)
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 }
101}
102
110ROXML_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
127ROXML_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 }
142}
143
144ROXML_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
165ROXML_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 }
218}
219
220ROXML_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
229ROXML_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
238ROXML_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
262ROXML_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
281ROXML_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
313ROXML_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
353ROXML_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_CMT_NODE
Definition roxml.h:86
#define ROXML_NON_ESCAPABLE_NODES
Definition roxml.h:174
#define ENCODE
Definition roxml.h:182
#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_ESCAPED_MOD
Definition roxml.h:166
#define ROXML_API
Definition roxml.h:24
#define ROXML_CDATA_NODE
Definition roxml.h:126
#define ROXML_DOCTYPE_NODE
Definition roxml.h:134
ROXML_API int roxml_get_nodes_nb(node_t *n, int type)
number of nodes getter function
ROXML_API int roxml_get_attr_nb(node_t *n)
number of attribute getter function
ROXML_API int roxml_escape(const char *buf, int decode, char *out)
XML encoding/decoding function.
ROXML_INT node_t * roxml_create_node(int pos, void *src, int type)
internal function
Definition roxml_core.c:46
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_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_INT void roxml_free_node(node_t *n)
internal function
Definition roxml_core.c:82
XML parsing core module.
#define ROXML_BUFF
#define ROXML_PENDING
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
ROXML_STATIC ROXML_INT void roxml_del_arg_node(node_t *n)
attribute node deletion function
Definition roxml_edit.c:127
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
ROXML_API void roxml_del_node(node_t *n)
node deletion function
Definition roxml_edit.c:204
ROXML_STATIC ROXML_INT void roxml_del_std_node(node_t *n)
node deletion function
Definition roxml_edit.c:85
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_txt_node(node_t *n)
text node deletion function
Definition roxml_edit.c:110
ROXML_STATIC ROXML_INT void roxml_reset_ns(node_t *n, node_t *ns)
internal function
Definition roxml_edit.c:48
ROXML_API node_t * roxml_set_ns(node_t *n, node_t *ns)
namespace setter function
Definition roxml_edit.c:395
XML internal memory management module.
node_t structure
struct node * prnt
unsigned short type
struct node * ns
roxml_pos_t end
void * priv
void * src
struct node * chld
struct node * attr
struct node * sibl
namespace structure
unsigned char id
char * alias