1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include <cx/utils.h>
34 #include <cx/printf.h>
35
36 #include "xml.h"
37
38 static DavXmlNodeType convert_type(xmlElementType type) {
39 DavXmlNodeType ct;
40 switch(type) {
41 default: ct =
DAV_XML_NONE;
break;
42 case XML_ELEMENT_NODE: ct =
DAV_XML_ELEMENT;
break;
43 case XML_TEXT_NODE: ct =
DAV_XML_TEXT;
44 }
45 return ct;
46 }
47
48 typedef struct {
49 xmlNode *node;
50 DavXmlNode *parent;
51 } ConvXmlElm;
52
53 DavXmlNode* dav_convert_xml(DavSession *sn, xmlNode *node) {
54 if(!node) {
55 return NULL;
56 }
57 DavXmlNodeType newnt = convert_type(node->type);
58 if(newnt ==
DAV_XML_NONE) {
59 return NULL;
60 }
61
62 const CxAllocator *a = sn->mp->allocator;
63
64 ConvXmlElm ce;
65 ce.node = node;
66 ce.parent =
NULL;
67 CxList *stack = cxLinkedListCreate(cxDefaultAllocator,
NULL,
sizeof(ConvXmlElm));
68 if(!stack) {
69 return NULL;
70 }
71 cxListInsert(stack,
0, &ce);
72
73 DavXmlNode *ret =
NULL;
74
75 while(cxListSize(stack) >
0) {
76 ConvXmlElm *c = cxListAt(stack,
0);
77 xmlNode *n = c->node;
78 DavXmlNode *c_parent = c->parent;
79 DavXmlNode *prev =
NULL;
80 cxListRemove(stack,
0);
81 while(n) {
82 DavXmlNode *newxn = cxCalloc(a,
1,
sizeof(DavXmlNode));
83 if(!ret) {
84 ret = newxn;
85 }
86 newxn->type = convert_type(n->type);
87 newxn->parent = c_parent;
88 if(c_parent && !c_parent->children) {
89 c_parent->children = newxn;
90 }
91 newxn->prev = prev;
92 if(prev) {
93 prev->next = newxn;
94 }
95
96 if(newxn->type ==
DAV_XML_ELEMENT) {
97 newxn->name = dav_session_strdup(sn, (
char*)n->name);
98 if(n->ns && n->ns->href) {
99 newxn->namespace = dav_session_strdup(sn, (
char*)n->ns->href);
100 }
101
102 xmlAttr *attr = n->properties;
103 DavXmlAttr *newattr =
NULL;
104 DavXmlAttr *newattr_last =
NULL;
105 while(attr) {
106 DavXmlAttr *na = cxCalloc(a,
1,
sizeof(DavXmlAttr));
107 na->name = dav_session_strdup(sn, (
char*)attr->name);
108 if(attr->children && attr->children->type ==
XML_TEXT_NODE) {
109 na->value = dav_session_strdup(sn, (
char*)attr->children->content);
110 }
111 if(!newattr) {
112 newattr = na;
113 }
else {
114 newattr_last->next = na;
115 }
116 newattr_last = na;
117
118 attr = attr->next;
119 }
120 newxn->attributes = newattr;
121
122 if(n->children) {
123 ConvXmlElm convc;
124 convc.node = n->children;
125 convc.parent = newxn;
126 cxListInsert(stack,
0, &convc);
127 }
128 }
else if(newxn->type ==
DAV_XML_TEXT) {
129 cxmutstr content = cx_strdup_a(a, cx_str((
char*)n->content));
130 newxn->content = content.ptr;
131 newxn->contentlength = content.length;
132 }
133
134 prev = newxn;
135 n = n->next;
136 }
137 }
138
139 return ret;
140 }
141
142 void dav_print_xml(DavXmlNode *node) {
143 if(node->type ==
DAV_XML_ELEMENT) {
144 printf(
"<%s", node->name);
145 DavXmlAttr *attr = node->attributes;
146 while(attr) {
147 printf(
" %s=\"%s\"", attr->name, attr->value);
148 attr = attr->next;
149 }
150 putchar(
'>');
151
152 DavXmlNode *child = node->children;
153 if(child) {
154 dav_print_xml(child);
155 }
156
157 printf(
"</%s>", node->name);
158 }
else {
159 fwrite(node->content,
1, node->contentlength, stdout);
160 fflush(stdout);
161 }
162 if(node->next) {
163 dav_print_xml(node->next);
164 }
165 }
166
167 void dav_print_node(
void *stream, cx_write_func writef, CxMap *nsmap, DavXmlNode *node) {
168 while(node) {
169 if(node->type ==
DAV_XML_ELEMENT) {
170 char *tagend = node->children ?
">" :
" />";
171 char *prefix =
NULL;
172 char *prefix_fr =
NULL;
173 if(node->namespace) {
174 prefix = cxMapGet(nsmap, cx_hash_key_str(node->namespace));
175 if(!prefix) {
176 cxmutstr newpre = cx_asprintf(
"x%zu", cxMapSize(nsmap)+
1);
177
178
179 prefix = newpre.ptr;
180 prefix_fr = prefix;
181 cx_fprintf(
182 stream,
183 writef,
184 "<%s:%s xmlns:%s=\"%s\"",
185 prefix,
186 node->name,
187 prefix,
188 node->namespace);
189 }
else {
190 cx_fprintf(stream, writef,
"<%s:%s", prefix, node->name);
191 }
192 }
else {
193 cx_fprintf(stream, writef,
"<%s", node->name);
194 }
195
196 DavXmlAttr *attr = node->attributes;
197 while(attr) {
198 cx_fprintf(stream, writef,
" %s=\"%s\"", attr->name, attr->value);
199 attr = attr->next;
200 }
201 writef(tagend,
1, strlen(tagend), stream);
202
203 if(node->children) {
204 dav_print_node(stream, writef, nsmap, node->children);
205 if(prefix) {
206 cx_fprintf(stream, writef,
"</%s:%s>", prefix, node->name);
207 }
else {
208 cx_fprintf(stream, writef,
"</%s>", node->name);
209 }
210 }
211
212 if(prefix_fr) {
213 free(prefix_fr);
214 }
215 }
else if(node->type ==
DAV_XML_TEXT) {
216 writef(node->content,
1, node->contentlength, stream);
217 }
218
219 node = node->next;
220 }
221 }
222
223
224
225 char* dav_xml_getstring(DavXmlNode *node) {
226 if(node && node->type ==
DAV_XML_TEXT) {
227 return node->content;
228 }
else {
229 return NULL;
230 }
231 }
232
233 DavBool dav_xml_isstring(DavXmlNode *node) {
234 if(node && node->type ==
DAV_XML_TEXT && !node->next) {
235 return TRUE;
236 }
else {
237 return FALSE;
238 }
239 }
240
241 DavXmlNode* dav_xml_nextelm(DavXmlNode *node) {
242 node = node->next;
243 while(node) {
244 if(node->type ==
DAV_XML_ELEMENT) {
245 return node;
246 }
247 node = node->next;
248 }
249 return NULL;
250 }
251
252 DavXmlNode* dav_text_node(DavSession *sn,
const char *text) {
253 const CxAllocator *a = sn->mp->allocator;
254 DavXmlNode *newxn = cxCalloc(a,
1,
sizeof(DavXmlNode));
255 newxn->type =
DAV_XML_TEXT;
256 cxmutstr content = cx_strdup_a(a, cx_str(text));
257 newxn->content = content.ptr;
258 newxn->contentlength = content.length;
259 return newxn;
260 }
261
262 DavXmlNode* dav_text_element(DavSession *sn,
const char *ns,
const char *name,
const char *text) {
263 const CxAllocator *a = sn->mp->allocator;
264 DavXmlNode *newelm = cxCalloc(a,
1,
sizeof(DavXmlNode));
265 newelm->type =
DAV_XML_ELEMENT;
266 newelm->namespace = cx_strdup_a(a, cx_str(ns)).ptr;
267 newelm->name = cx_strdup_a(a, cx_str(name)).ptr;
268 newelm->children = dav_text_node(sn, text);
269 return newelm;
270 }
271
272 static void dav_free_xml_node_a(
const CxAllocator *a, DavXmlNode *node) {
273 if(node->name) cxFree(a, node->name);
274 if(node->namespace) cxFree(a, node->namespace);
275 if(node->content) cxFree(a, node->content);
276 DavXmlAttr *attr = node->attributes;
277 while(attr) {
278 if(attr->name) cxFree(a, attr->name);
279 if(attr->value) cxFree(a, attr->value);
280 attr = attr->next;
281 }
282 DavXmlNode *children = node->children;
283 while(children) {
284 DavXmlNode *next_ch = children->next;
285 dav_free_xml_node_a(a, children);
286 children = next_ch;
287 }
288 cxFree(a, node);
289 }
290
291 void dav_free_xml_node_sn(DavSession *sn, DavXmlNode *node) {
292 dav_free_xml_node_a(sn->mp->allocator, node);
293 }
294
295 void dav_free_xml_node(DavXmlNode *node) {
296 dav_free_xml_node_a(cxDefaultAllocator, node);
297 }
298
299 DavXmlAttr* dav_copy_xml_attr(DavXmlAttr *attr) {
300 if(!attr) {
301 return NULL;
302 }
303 DavXmlAttr *newattr =
NULL;
304 DavXmlAttr *prev =
NULL;
305 while(attr) {
306 DavXmlAttr *n = calloc(
1,
sizeof(DavXmlAttr));
307 n->name = strdup(attr->name);
308 n->value = strdup(attr->value);
309 if(prev) {
310 prev->next = n;
311 }
else {
312 newattr = n;
313 }
314 prev = n;
315 attr = attr->next;
316 }
317 return newattr;
318 }
319
320 DavXmlNode* dav_copy_node(DavXmlNode *node) {
321 DavXmlNode *ret =
NULL;
322 DavXmlNode *prev =
NULL;
323 while(node) {
324 DavXmlNode *copy = calloc(
1,
sizeof(DavXmlNode));
325 copy->type = node->type;
326 if(node->type ==
DAV_XML_ELEMENT) {
327 copy->namespace = strdup(node->namespace);
328 copy->name = strdup(node->name);
329 copy->children = dav_copy_node(node->children);
330 copy->attributes = dav_copy_xml_attr(node->attributes);
331 }
else {
332 copy->contentlength = node->contentlength;
333 copy->content = malloc(node->contentlength+
1);
334 memcpy(copy->content, node->content, node->contentlength);
335 copy->content[copy->contentlength] =
0;
336 }
337 if(!ret) {
338 ret = copy;
339 }
340 if(prev) {
341 prev->next = copy;
342 copy->prev = prev;
343 }
344 prev = copy;
345 node = node->next;
346 }
347 return ret;
348 }
349
350
351 DavXmlNode* dav_xml_createnode(
const char *ns,
const char *name) {
352 DavXmlNode *node = calloc(
1,
sizeof(DavXmlNode));
353 node->type =
DAV_XML_ELEMENT;
354 node->namespace = strdup(ns);
355 node->name = strdup(name);
356 return node;
357 }
358
359 DavXmlNode* dav_xml_createnode_with_text(
const char *ns,
const char *name,
const char *text) {
360 DavXmlNode *node = calloc(
1,
sizeof(DavXmlNode));
361 node->type =
DAV_XML_ELEMENT;
362 node->namespace = strdup(ns);
363 node->name = strdup(name);
364
365 DavXmlNode *textnode = dav_xml_createtextnode(text);
366 node->children = textnode;
367
368 return node;
369 }
370
371 DavXmlNode* dav_xml_createtextnode(
const char *text) {
372 DavXmlNode *node = calloc(
1,
sizeof(DavXmlNode));
373 node->type =
DAV_XML_TEXT;
374 cxmutstr content = cx_strdup(cx_str((
char*)text));
375 node->content = content.ptr;
376 node->contentlength = content.length;
377 return node;
378 }
379
380 void dav_xml_add_child(DavXmlNode *node, DavXmlNode *child) {
381 DavXmlNode *last_child =
NULL;
382 DavXmlNode *c = node->children;
383 while(c) {
384 last_child = c;
385 c = c->next;
386 }
387 if(last_child) {
388 last_child->next = child;
389 child->prev = last_child;
390 }
else {
391 node->children = child;
392 }
393 }
394
395 void dav_xml_add_attr(DavXmlNode *node,
const char *name,
const char *value) {
396 DavXmlAttr *attr = calloc(
1,
sizeof(DavXmlAttr));
397 attr->name = strdup(name);
398 attr->value = strdup(value);
399
400 if(node->attributes) {
401 DavXmlAttr *end = node->attributes;
402 DavXmlAttr* last = end;
403 while(end) {
404 last = end;
405 end = end->next;
406 }
407 last->next = attr;
408 }
else {
409 node->attributes = attr;
410 }
411 }
412
413 char* dav_xml_get_attr(DavXmlNode *node,
const char *name) {
414 DavXmlAttr *attr = node->attributes;
415 while(attr) {
416 if(!strcmp(attr->name, name)) {
417 return attr->value;
418 }
419
420 attr = attr->next;
421 }
422 return NULL;
423 }
424
425 DavXmlNode* dav_parse_xml(DavSession *sn,
const char *str,
size_t len) {
426 xmlDoc *doc = xmlReadMemory(str, len,
NULL,
NULL,
0);
427 if(!doc) {
428 return NULL;
429 }
430 xmlNode *xml_root = xmlDocGetRootElement(doc);
431 if(!xml_root) {
432 xmlFreeDoc(doc);
433 return NULL;
434 }
435 DavXmlNode *x = dav_convert_xml(sn, xml_root);
436 xmlFreeDoc(doc);
437 return x;
438 }
439