1 /*
2 * libwbxml, the WBXML Library.
3 * Copyright (C) 2002-2008 Aymerick Jehanne <aymerick@jehanne.org>
4 * Copyright (C) 2008-2011 Michael Bell <michael.bell@opensync.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * LGPL v2.1: http://www.gnu.org/copyleft/lesser.txt
21 *
22 * Contact: aymerick@jehanne.org
23 * Home: http://libwbxml.aymerick.com
24 */
25
26 /**
27 * @file wbxml_tree.c
28 * @ingroup wbxml_tree
29 *
30 * @author Aymerick Jehanne <aymerick@jehanne.org>
31 * @date 03/02/18
32 *
33 * @brief WBXML Tree
34 */
35
36 #include "wbxml_config_internals.h"
37 #include "wbxml_tree.h"
38 #include "wbxml_log.h"
39 #include "wbxml_parser.h"
40 #include "wbxml_encoder.h"
41 #include "wbxml_tree_clb_xml.h"
42 #include "wbxml_tree_clb_wbxml.h"
43 #include "wbxml_internals.h"
44
45 /***************************************************
46 * Public Functions
47 */
48
wbxml_tree_from_wbxml(WB_UTINY * wbxml,WB_ULONG wbxml_len,WBXMLLanguage lang,WBXMLCharsetMIBEnum charset,WBXMLTree ** tree)49 WBXML_DECLARE(WBXMLError) wbxml_tree_from_wbxml(WB_UTINY *wbxml,
50 WB_ULONG wbxml_len,
51 WBXMLLanguage lang,
52 WBXMLCharsetMIBEnum charset,
53 WBXMLTree **tree)
54 {
55 WBXMLParser *wbxml_parser = NULL;
56 WB_LONG error_index = 0;
57 WBXMLTreeClbCtx wbxml_tree_clb_ctx;
58 WBXMLError ret = WBXML_OK;
59 WBXMLContentHandler wbxml_tree_content_handler =
60 {
61 wbxml_tree_clb_wbxml_start_document,
62 wbxml_tree_clb_wbxml_end_document,
63 wbxml_tree_clb_wbxml_start_element,
64 wbxml_tree_clb_wbxml_end_element,
65 wbxml_tree_clb_wbxml_characters,
66 wbxml_tree_clb_wbxml_pi
67 };
68
69 if (tree != NULL)
70 *tree = NULL;
71
72 /* Create WBXML Parser */
73 if((wbxml_parser = wbxml_parser_create()) == NULL) {
74 WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Parser"));
75 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
76 }
77
78 /* Init context */
79 wbxml_tree_clb_ctx.error = WBXML_OK;
80 wbxml_tree_clb_ctx.current = NULL;
81 if ((wbxml_tree_clb_ctx.tree = wbxml_tree_create(WBXML_LANG_UNKNOWN, WBXML_CHARSET_UNKNOWN)) == NULL) {
82 wbxml_parser_destroy(wbxml_parser);
83 WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Tree"));
84 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
85 }
86
87 /* Set Handlers Callbacks */
88 wbxml_parser_set_user_data(wbxml_parser, &wbxml_tree_clb_ctx);
89 wbxml_parser_set_content_handler(wbxml_parser, &wbxml_tree_content_handler);
90
91 /* Give the user the possibility to force Document Language */
92 if (lang != WBXML_LANG_UNKNOWN)
93 wbxml_parser_set_language(wbxml_parser, lang);
94
95 /* Give the user the possibility to force the document character set */
96 if (charset != WBXML_CHARSET_UNKNOWN)
97 wbxml_parser_set_meta_charset(wbxml_parser, charset);
98
99 /* Parse the WBXML document to WBXML Tree */
100 ret = wbxml_parser_parse(wbxml_parser, wbxml, wbxml_len);
101 if ((ret != WBXML_OK) || (wbxml_tree_clb_ctx.error != WBXML_OK))
102 {
103 error_index = wbxml_parser_get_current_byte_index(wbxml_parser);
104 WBXML_ERROR((WBXML_PARSER, "WBXML Parser failed at %ld - token: %x (%s)",
105 error_index,
106 wbxml[error_index],
107 ret != WBXML_OK ? wbxml_errors_string(ret) : wbxml_errors_string(wbxml_tree_clb_ctx.error)));
108
109 wbxml_tree_destroy(wbxml_tree_clb_ctx.tree);
110 }
111 else {
112 *tree = wbxml_tree_clb_ctx.tree;
113 }
114
115 /* Clean-up */
116 wbxml_parser_destroy(wbxml_parser);
117
118 if (ret != WBXML_OK)
119 return ret;
120 else
121 return wbxml_tree_clb_ctx.error;
122 }
123
124
wbxml_tree_to_wbxml(WBXMLTree * tree,WB_UTINY ** wbxml,WB_ULONG * wbxml_len,WBXMLGenWBXMLParams * params)125 WBXML_DECLARE(WBXMLError) wbxml_tree_to_wbxml(WBXMLTree *tree,
126 WB_UTINY **wbxml,
127 WB_ULONG *wbxml_len,
128 WBXMLGenWBXMLParams *params)
129 {
130 WBXMLEncoder *wbxml_encoder = NULL;
131 WBXMLError ret = WBXML_OK;
132
133 /* Encode WBXML Tree to WBXML Document */
134 if ((wbxml_encoder = wbxml_encoder_create()) == NULL) {
135 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
136 }
137
138 /* Set the WBXML Tree to encode */
139 wbxml_encoder_set_tree(wbxml_encoder, tree);
140
141 /* Set encoder parameters */
142 if (params == NULL) {
143 /* Default Parameters */
144
145 /* Ignores "Empty Text" Nodes */
146 wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE);
147
148 /* Remove leading and trailing whitespaces in "Text Nodes" */
149 wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE);
150
151 /* Use String Table */
152 wbxml_encoder_set_use_strtbl(wbxml_encoder, TRUE);
153
154 /* Don't produce an anonymous document by default */
155 wbxml_encoder_set_produce_anonymous(wbxml_encoder, FALSE);
156 }
157 else {
158 /* WBXML Version */
159 wbxml_encoder_set_wbxml_version(wbxml_encoder, params->wbxml_version);
160
161 /* Keep Ignorable Whitespaces ? */
162 if (!params->keep_ignorable_ws) {
163 /* Ignores "Empty Text" Nodes */
164 wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE);
165
166 /* Remove leading and trailing whitespaces in "Text Nodes" */
167 wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE);
168 }
169
170 /* String Table */
171 wbxml_encoder_set_use_strtbl(wbxml_encoder, params->use_strtbl);
172
173 /* Produce an anonymous document? */
174 wbxml_encoder_set_produce_anonymous(wbxml_encoder,
175 params->produce_anonymous);
176
177 /** @todo Add parameter to call : wbxml_encoder_set_output_charset() */
178 }
179
180 /* Encode WBXML */
181 ret = wbxml_encoder_encode_to_wbxml(wbxml_encoder, wbxml, wbxml_len);
182
183 /* Clean-up */
184 wbxml_encoder_destroy(wbxml_encoder);
185
186 return ret;
187 }
188
189
wbxml_tree_from_xml(WB_UTINY * xml,WB_ULONG xml_len,WBXMLTree ** tree)190 WBXML_DECLARE(WBXMLError) wbxml_tree_from_xml(WB_UTINY *xml, WB_ULONG xml_len, WBXMLTree **tree)
191 {
192 #if defined( HAVE_EXPAT )
193
194 const XML_Feature *feature_list = NULL;
195 XML_Parser xml_parser = NULL;
196 WBXMLError ret = WBXML_OK;
197 WB_BOOL expat_utf16 = FALSE;
198 WBXMLTreeClbCtx wbxml_tree_clb_ctx;
199
200 if ((xml == NULL) || (xml_len == 0) || (tree == NULL))
201 return WBXML_ERROR_BAD_PARAMETER;
202
203 /* Clean up pointer */
204 *tree = NULL;
205
206 /* First Check if Expat is outputing UTF-16 strings */
207 feature_list = (const XML_Feature *)XML_GetFeatureList();
208
209 if ((feature_list != NULL) && (feature_list[0].value != sizeof(WB_TINY))) {
210 #if !defined( HAVE_ICONV )
211 /* Ouch, can't convert from UTF-16 to UTF-8 */
212 return WBXML_ERROR_XMLPARSER_OUTPUT_UTF16;
213 #else
214 /* Expat returns UTF-16 encoded strings in its callbacks */
215 expat_utf16 = TRUE;
216 #endif /* !HAVE_ICONV */
217 }
218
219 /* Create Expat XML Parser */
220 if ((xml_parser = XML_ParserCreateNS(NULL, WBXML_NAMESPACE_SEPARATOR)) == NULL)
221 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
222
223 /* Init context */
224 wbxml_tree_clb_ctx.current = NULL;
225 wbxml_tree_clb_ctx.error = WBXML_OK;
226 wbxml_tree_clb_ctx.skip_lvl = 0;
227 wbxml_tree_clb_ctx.skip_start = 0;
228 wbxml_tree_clb_ctx.xml_parser = xml_parser;
229 wbxml_tree_clb_ctx.input_buff = xml;
230 wbxml_tree_clb_ctx.expat_utf16 = expat_utf16;
231
232 /* Create WBXML Tree */
233 if ((wbxml_tree_clb_ctx.tree = wbxml_tree_create(WBXML_LANG_UNKNOWN, WBXML_CHARSET_UNKNOWN)) == NULL) {
234 XML_ParserFree(xml_parser);
235 WBXML_ERROR((WBXML_PARSER, "Can't create WBXML Tree"));
236 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
237 }
238
239 /* Set Handlers Callbacks */
240 XML_SetXmlDeclHandler(xml_parser, wbxml_tree_clb_xml_decl);
241 XML_SetStartDoctypeDeclHandler(xml_parser, wbxml_tree_clb_xml_doctype_decl);
242 XML_SetElementHandler(xml_parser, wbxml_tree_clb_xml_start_element, wbxml_tree_clb_xml_end_element);
243 XML_SetCdataSectionHandler(xml_parser, wbxml_tree_clb_xml_start_cdata, wbxml_tree_clb_xml_end_cdata);
244 XML_SetProcessingInstructionHandler(xml_parser , wbxml_tree_clb_xml_pi);
245 XML_SetCharacterDataHandler(xml_parser, wbxml_tree_clb_xml_characters);
246 XML_SetUserData(xml_parser, (void*)&wbxml_tree_clb_ctx);
247
248 /* Parse the XML Document to WBXML Tree */
249 if (XML_Parse(xml_parser, (WB_TINY*) xml, xml_len, TRUE) == 0)
250 {
251 WBXML_ERROR((WBXML_CONV, "xml2wbxml conversion failed - expat error %i\n"
252 "\tdescription: %s\n"
253 "\tline: %i\n"
254 "\tcolumn: %i\n"
255 "\tbyte index: %i\n"
256 "\ttotal bytes: %i\n%s",
257 XML_GetErrorCode(xml_parser),
258 XML_ErrorString(XML_GetErrorCode(xml_parser)),
259 XML_GetCurrentLineNumber(xml_parser),
260 XML_GetCurrentColumnNumber(xml_parser),
261 XML_GetCurrentByteIndex(xml_parser),
262 XML_GetCurrentByteCount(xml_parser), xml));
263
264 wbxml_tree_destroy(wbxml_tree_clb_ctx.tree);
265
266 ret = WBXML_ERROR_XML_PARSING_FAILED;
267 }
268 else {
269 if ((ret = wbxml_tree_clb_ctx.error) != WBXML_OK)
270 {
271 WBXML_ERROR((WBXML_CONV, "xml2wbxml conversion failed - context error %i", ret));
272 wbxml_tree_destroy(wbxml_tree_clb_ctx.tree);
273 }
274 else
275 *tree = wbxml_tree_clb_ctx.tree;
276 }
277
278 /* Clean-up */
279 XML_ParserFree(xml_parser);
280
281 return ret;
282
283 #else /* HAVE_EXPAT */
284
285 #if defined( HAVE_LIBXML )
286
287 /** @todo Use LibXML2 SAX interface ! */
288 return WBXML_ERROR_NO_XMLPARSER;
289
290 #else /* HAVE_LIBXML */
291
292 /** @note You can add here another XML Parser support */
293 return WBXML_ERROR_NO_XMLPARSER;
294
295 #endif /* HAVE_LIBXML */
296
297 #endif /* HAVE_EXPAT */
298 }
299
300
wbxml_tree_to_xml(WBXMLTree * tree,WB_UTINY ** xml,WB_ULONG * xml_len,WBXMLGenXMLParams * params)301 WBXML_DECLARE(WBXMLError) wbxml_tree_to_xml(WBXMLTree *tree,
302 WB_UTINY **xml,
303 WB_ULONG *xml_len,
304 WBXMLGenXMLParams *params)
305 {
306 WBXMLEncoder *wbxml_encoder = NULL;
307 WBXMLError ret = WBXML_OK;
308
309 /* Create WBXML Encoder */
310 if ((wbxml_encoder = wbxml_encoder_create()) == NULL) {
311 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
312 }
313
314 /* Set the WBXML Tree to encode */
315 wbxml_encoder_set_tree(wbxml_encoder, tree);
316
317 /* Set encoder parameters */
318 if (params == NULL) {
319 /* Default Values */
320
321 /* Set XML Generation Type */
322 wbxml_encoder_set_xml_gen_type(wbxml_encoder, WBXML_GEN_XML_INDENT);
323
324 /* Set Indent */
325 wbxml_encoder_set_indent(wbxml_encoder, 0);
326
327 /* Skip Ignorable Whitespaces */
328 wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE);
329 wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE);
330 }
331 else {
332 /* Set XML Generation Type */
333 wbxml_encoder_set_xml_gen_type(wbxml_encoder, params->gen_type);
334
335 /* Set Indent */
336 if (params->gen_type == WBXML_GEN_XML_INDENT)
337 wbxml_encoder_set_indent(wbxml_encoder, params->indent);
338
339 /* Ignorable Whitespaces */
340 if (params->keep_ignorable_ws) {
341 wbxml_encoder_set_ignore_empty_text(wbxml_encoder, FALSE);
342 wbxml_encoder_set_remove_text_blanks(wbxml_encoder, FALSE);
343 }
344 else {
345 wbxml_encoder_set_ignore_empty_text(wbxml_encoder, TRUE);
346 wbxml_encoder_set_remove_text_blanks(wbxml_encoder, TRUE);
347 }
348
349 /** @todo Add parameter to call : wbxml_encoder_set_output_charset() */
350 }
351
352 /* Encode WBXML Tree to XML */
353 ret = wbxml_encoder_encode_tree_to_xml(wbxml_encoder, xml, xml_len);
354
355 /* Clean-up */
356 wbxml_encoder_destroy(wbxml_encoder);
357
358 return ret;
359 }
360
361
362 #if defined( HAVE_LIBXML )
363
wbxml_tree_from_libxml_doc(xmlDocPtr libxml_doc,WBXMLTree ** tree)364 WBXML_DECLARE(WBXMLError) wbxml_tree_from_libxml_doc(xmlDocPtr libxml_doc,
365 WBXMLTree **tree)
366 {
367 /** @todo wbxml_tree_from_libxml_doc() */
368 return WBXML_ERROR_NOT_IMPLEMENTED;
369 }
370
371
wbxml_tree_to_libxml_doc(WBXMLTree * tree,xmlDocPtr * libxml_doc)372 WBXML_DECLARE(WBXMLError) wbxml_tree_to_libxml_doc(WBXMLTree *tree,
373 xmlDocPtr *libxml_doc)
374 {
375 /** @todo wbxml_tree_to_libxml_doc() */
376 return WBXML_ERROR_NOT_IMPLEMENTED;
377 }
378
379 #endif /* HAVE_LIBXML */
380
381
wbxml_tree_node_create(WBXMLTreeNodeType type)382 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create(WBXMLTreeNodeType type)
383 {
384 WBXMLTreeNode *result = NULL;
385
386 if ((result = wbxml_malloc(sizeof(WBXMLTreeNode))) == NULL)
387 return NULL;
388
389 result->type = type;
390 result->name = NULL;
391 result->attrs = NULL;
392 result->content = NULL;
393 result->tree = NULL;
394
395 result->parent = NULL;
396 result->children = NULL;
397 result->next = NULL;
398 result->prev = NULL;
399
400 return result;
401 }
402
403
wbxml_tree_node_destroy(WBXMLTreeNode * node)404 WBXML_DECLARE(void) wbxml_tree_node_destroy(WBXMLTreeNode *node)
405 {
406 if (node == NULL)
407 return;
408
409 wbxml_tag_destroy(node->name);
410 wbxml_list_destroy(node->attrs, wbxml_attribute_destroy_item);
411 wbxml_buffer_destroy(node->content);
412 wbxml_tree_destroy(node->tree);
413
414 wbxml_free(node);
415 }
416
417
wbxml_tree_node_destroy_item(void * node)418 WBXML_DECLARE(void) wbxml_tree_node_destroy_item(void *node)
419 {
420 wbxml_tree_node_destroy((WBXMLTreeNode *)node);
421 }
422
423
wbxml_tree_node_destroy_all(WBXMLTreeNode * node)424 WBXML_DECLARE(void) wbxml_tree_node_destroy_all(WBXMLTreeNode *node)
425 {
426 WBXMLTreeNode *parent_node = NULL;
427 WBXMLTreeNode *current_node = NULL;
428 WBXMLTreeNode *previous_node = NULL;
429 WBXMLTreeNode *tmp_node = NULL;
430 WB_BOOL end_of_walk = FALSE;
431
432 if (node == NULL)
433 return;
434
435 /* Let's go through the sub-tree (iteratively) to free all the nodes */
436 current_node = node;
437 parent_node = node->parent;
438
439 while (!end_of_walk)
440 {
441 if (current_node == NULL) {
442 /* Leaf reached */
443 if (previous_node == NULL) {
444 end_of_walk = TRUE;
445 break;
446 }
447 else {
448 if (previous_node->parent == parent_node) {
449 /* End of parsing, we have parsed the last child of node */
450 end_of_walk = TRUE;
451 break;
452 }
453 else {
454 /* Let's parse next child of parent node */
455 current_node = previous_node->next;
456 tmp_node = previous_node->parent;
457
458 /* Destroy this node (leaf) */
459 wbxml_tree_node_destroy(previous_node);
460
461 previous_node = tmp_node;
462 }
463 }
464 }
465 else {
466 /* Go deeper in sub-tree */
467 previous_node = current_node;
468 current_node = current_node->children;
469 }
470 }
471
472 wbxml_tree_node_destroy(node);
473 }
474
475
wbxml_tree_node_create_xml_elt(const WBXMLLangEntry * lang_table,const WB_UTINY * name)476 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create_xml_elt(const WBXMLLangEntry *lang_table,
477 const WB_UTINY *name)
478 {
479 const WBXMLTagEntry *tag_entry = NULL;
480 WBXMLTreeNode *node = NULL;
481 WBXMLTag *tag = NULL;
482
483 /* Search for XML Tag Name in Table */
484 if ((tag_entry = wbxml_tables_get_tag_from_xml(lang_table, -1, name)) != NULL) {
485 /* Found : token tag */
486 tag = wbxml_tag_create_token(tag_entry);
487 }
488 else {
489 /* Not found : literal tag */
490 tag = wbxml_tag_create_literal((WB_UTINY *)name);
491 }
492
493 if (tag == NULL)
494 return NULL;
495
496 /* Create a new Node */
497 if ((node = wbxml_tree_node_create(WBXML_TREE_ELEMENT_NODE)) == NULL) {
498 wbxml_tag_destroy(tag);
499 return NULL;
500 }
501
502 /* Set Node Tag */
503 node->name = tag;
504
505 return node;
506 }
507
508
wbxml_tree_node_create_xml_elt_with_text(const WBXMLLangEntry * lang_table,const WB_UTINY * name,const WB_UTINY * text,WB_ULONG len)509 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create_xml_elt_with_text(const WBXMLLangEntry *lang_table,
510 const WB_UTINY *name,
511 const WB_UTINY *text,
512 WB_ULONG len)
513 {
514 WBXMLTreeNode *node = NULL;
515 WBXMLTreeNode *text_node = NULL;
516
517 /* Create element node */
518 if ((node = wbxml_tree_node_create_xml_elt(lang_table, name)) == NULL)
519 return NULL;
520
521 /* Create text node */
522 if ((text_node = wbxml_tree_node_create_text(text, len)) == NULL) {
523 wbxml_tree_node_destroy(node);
524 return NULL;
525 }
526
527 /* Add text node to element node */
528 if (!wbxml_tree_node_add_child(node, text_node)) {
529 wbxml_tree_node_destroy(node);
530 wbxml_tree_node_destroy(text_node);
531 return NULL;
532 }
533
534 return node;
535 }
536
537
wbxml_tree_node_create_text(const WB_UTINY * text,WB_ULONG len)538 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create_text(const WB_UTINY *text,
539 WB_ULONG len)
540 {
541 WBXMLTreeNode *node = NULL;
542
543 /* Create a new Node */
544 if ((node = wbxml_tree_node_create(WBXML_TREE_TEXT_NODE)) == NULL) {
545 return NULL;
546 }
547
548 /* Set Content */
549 if ((node->content = wbxml_buffer_create(text, len, len)) == NULL) {
550 wbxml_tree_node_destroy(node);
551 return NULL;
552 }
553
554 return node;
555 }
556
557
wbxml_tree_node_create_cdata(const WB_UTINY * text,WB_ULONG len)558 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create_cdata(const WB_UTINY *text,
559 WB_ULONG len)
560 {
561 WBXMLTreeNode *node = NULL;
562 WBXMLTreeNode *text_node = NULL;
563
564 /* Create a new node */
565 if ((node = wbxml_tree_node_create(WBXML_TREE_CDATA_NODE)) == NULL) {
566 return NULL;
567 }
568
569 /* Create a text node */
570 if ((text_node = wbxml_tree_node_create_text(text, len)) == NULL) {
571 wbxml_tree_node_destroy(node);
572 return NULL;
573 }
574
575 /* Add text node to cdata */
576 if (!wbxml_tree_node_add_child(node, text_node)) {
577 wbxml_tree_node_destroy_all(node);
578 node = NULL;
579 }
580
581 return node;
582 }
583
584
wbxml_tree_node_create_tree(WBXMLTreeNode * root,WBXMLLanguage lang,WBXMLCharsetMIBEnum orig_charset)585 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_create_tree(WBXMLTreeNode *root,
586 WBXMLLanguage lang,
587 WBXMLCharsetMIBEnum orig_charset)
588 {
589 WBXMLTreeNode* result = NULL;
590 WBXMLTree* tree = NULL;
591
592 if ((root == NULL) || (lang == WBXML_LANG_UNKNOWN))
593 return NULL;
594
595 /* Create Tree */
596 if ((tree = wbxml_tree_create(lang, orig_charset)) == NULL)
597 return NULL;
598
599 /* Fill Tree */
600 tree->root = root;
601
602 /* Create Tree Node */
603 if ((result = wbxml_tree_node_create(WBXML_TREE_TREE_NODE)) == NULL) {
604 wbxml_tree_destroy(tree);
605 return NULL;
606 }
607
608 /* Fill Tree Node */
609 result->tree = tree;
610
611 return result;
612 }
613
614
wbxml_tree_node_add_child(WBXMLTreeNode * parent,WBXMLTreeNode * node)615 WBXML_DECLARE(WB_BOOL) wbxml_tree_node_add_child(WBXMLTreeNode *parent,
616 WBXMLTreeNode *node)
617 {
618 WBXMLTreeNode *tmp = NULL;
619
620 if ((parent == NULL) || (node == NULL))
621 return FALSE;
622
623 /* Set parent to new node */
624 node->parent = parent;
625
626 /* Search for previous sibbling element */
627 if (parent->children != NULL) {
628 /* Add this Node to end of Sibbling Node list of Parent */
629 tmp = parent->children;
630
631 while (tmp->next != NULL)
632 tmp = tmp->next;
633
634 node->prev = tmp;
635 tmp->next = node;
636 }
637 else {
638 /* No previous sibbling element */
639 parent->children = node;
640 }
641
642 return TRUE;
643 }
644
645
wbxml_tree_node_add_attr(WBXMLTreeNode * node,WBXMLAttribute * attr)646 WBXML_DECLARE(WBXMLError) wbxml_tree_node_add_attr(WBXMLTreeNode *node,
647 WBXMLAttribute *attr)
648 {
649 WBXMLAttribute *new_attr = NULL;
650
651 if ((node == NULL) || (attr == NULL)) {
652 return WBXML_ERROR_BAD_PARAMETER;
653 }
654
655 /* Create list if needed */
656 if (node->attrs == NULL) {
657 if ((node->attrs = wbxml_list_create()) == NULL) {
658 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
659 }
660 }
661
662 /* Duplicate Attribute */
663 if ((new_attr = wbxml_attribute_duplicate(attr)) == NULL)
664 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
665
666 /* Add attribute to list */
667 if (!wbxml_list_append(node->attrs, new_attr)) {
668 wbxml_attribute_destroy(attr);
669 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
670 }
671
672 return WBXML_OK;
673 }
674
675
wbxml_tree_node_add_attrs(WBXMLTreeNode * node,WBXMLAttribute ** attrs)676 WBXML_DECLARE(WBXMLError) wbxml_tree_node_add_attrs(WBXMLTreeNode *node,
677 WBXMLAttribute **attrs)
678 {
679 WB_ULONG i = 0;
680
681 if ((node == NULL) || (attrs == NULL)) {
682 return WBXML_ERROR_BAD_PARAMETER;
683 }
684
685 while (attrs[i] != NULL) {
686 /* Add attribute */
687 if (wbxml_tree_node_add_attr(node, attrs[i]) != WBXML_OK)
688 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
689
690 i++;
691 }
692
693 return WBXML_OK;
694 }
695
696
wbxml_tree_node_add_xml_attr(const WBXMLLangEntry * lang_table,WBXMLTreeNode * node,const WB_UTINY * name,const WB_UTINY * value)697 WBXML_DECLARE(WBXMLError) wbxml_tree_node_add_xml_attr(const WBXMLLangEntry *lang_table,
698 WBXMLTreeNode *node,
699 const WB_UTINY *name,
700 const WB_UTINY *value)
701 {
702 WBXMLAttribute *attr = NULL;
703 const WBXMLAttrEntry *attr_entry = NULL;
704
705 /* Create list if needed */
706 if (node->attrs == NULL) {
707 if ((node->attrs = wbxml_list_create()) == NULL) {
708 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
709 }
710 }
711
712 /* Create Attribute */
713 if ((attr = wbxml_attribute_create()) == NULL)
714 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
715
716 /* Set Attribute Name */
717 if ((attr_entry = wbxml_tables_get_attr_from_xml(lang_table, (WB_UTINY *)name, (WB_UTINY *)value, NULL)) != NULL)
718 attr->name = wbxml_attribute_name_create_token(attr_entry);
719 else
720 attr->name = wbxml_attribute_name_create_literal((WB_UTINY *)name);
721
722 if (attr->name == NULL) {
723 wbxml_attribute_destroy(attr);
724 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
725 }
726
727 /* Set Attribute Value */
728 attr->value = wbxml_buffer_create_real(value, WBXML_STRLEN(value), WBXML_STRLEN(value));
729 if (attr->value == NULL) {
730 wbxml_attribute_destroy(attr);
731 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
732 }
733
734 /* Add attribute to list */
735 if (!wbxml_list_append(node->attrs, attr)) {
736 wbxml_attribute_destroy(attr);
737 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
738 }
739
740 return WBXML_OK;
741 }
742
743
wbxml_tree_node_add_xml_attrs(const WBXMLLangEntry * lang_table,WBXMLTreeNode * node,const WB_UTINY ** attrs)744 WBXML_DECLARE(WBXMLError) wbxml_tree_node_add_xml_attrs(const WBXMLLangEntry *lang_table,
745 WBXMLTreeNode *node,
746 const WB_UTINY **attrs)
747 {
748 const WB_UTINY **p = attrs;
749
750 if ((lang_table == NULL) || (node == NULL) || (attrs == NULL))
751 return WBXML_ERROR_BAD_PARAMETER;
752
753 while (p && *p) {
754 /* Add attribute */
755 if (wbxml_tree_node_add_xml_attr(lang_table, node, *p, *(p+1)) != WBXML_OK)
756 return WBXML_ERROR_NOT_ENOUGH_MEMORY;
757
758 p += 2;
759 }
760
761 return WBXML_OK;
762 }
763
764
wbxml_tree_node_elt_get_from_name(WBXMLTreeNode * node,const char * name,WB_BOOL recurs)765 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_node_elt_get_from_name(WBXMLTreeNode *node, const char *name, WB_BOOL recurs)
766 {
767 WBXMLTreeNode *current_node = NULL;
768 WBXMLTreeNode *recurs_node = NULL;
769
770 if ((node == NULL) || (name == NULL))
771 return NULL;
772
773 /* Let's go through the tree */
774 current_node = node;
775
776 while (current_node != NULL)
777 {
778 /* Is this a normal node? */
779 if (current_node->type == WBXML_TREE_ELEMENT_NODE)
780 {
781 /* Is this the Node we searched ? */
782 if (WBXML_STRCMP(wbxml_tag_get_xml_name(current_node->name), name) == 0)
783 {
784 return current_node;
785 }
786
787 /* Sould we start a recursive search? */
788 if (recurs && current_node->children)
789 {
790 recurs_node = wbxml_tree_node_elt_get_from_name(current_node->children, name, TRUE);
791 /* Is this the Node we searched ? */
792 if (recurs_node)
793 {
794 return recurs_node;
795 }
796 }
797 }
798
799 /* Go to next Sibbling Node */
800 current_node = current_node->next;
801 }
802
803 /* A node with the specified name could not be found. */
804 return NULL;
805 }
806
807
808 #if defined ( WBXML_SUPPORT_SYNCML )
809
wbxml_tree_node_get_syncml_data_type(WBXMLTreeNode * node)810 WBXML_DECLARE(WBXMLSyncMLDataType) wbxml_tree_node_get_syncml_data_type(WBXMLTreeNode *node)
811 {
812 WBXMLTreeNode *tmp_node = NULL;
813
814 if (node == NULL)
815 return WBXML_SYNCML_DATA_TYPE_NORMAL;
816
817 /* If we are in a CDATA node then we must look into the parent node. */
818 if (node->type == WBXML_TREE_CDATA_NODE)
819 node = node->parent;
820
821 /* Are we in a <Data> ? */
822 if ((node->type == WBXML_TREE_ELEMENT_NODE) &&
823 (node->name != NULL) &&
824 (WBXML_STRCMP(wbxml_tag_get_xml_name(node->name), "Data") == 0))
825 {
826 /* Go to Parent element (or Parent of Parent) and search for <Meta> then <Type> */
827 if (((node->parent != NULL) &&
828 (node->parent->children != NULL) &&
829 ((tmp_node = wbxml_tree_node_elt_get_from_name(node->parent->children, "Meta", FALSE)) != NULL) &&
830 ((tmp_node = wbxml_tree_node_elt_get_from_name(tmp_node->children, "Type", FALSE)) != NULL)) ||
831 (((node->parent != NULL) &&
832 (node->parent->parent != NULL) &&
833 (node->parent->parent->children != NULL) &&
834 ((tmp_node = wbxml_tree_node_elt_get_from_name(node->parent->parent->children, "Meta", FALSE)) != NULL)) &&
835 ((tmp_node = wbxml_tree_node_elt_get_from_name(tmp_node->children, "Type", FALSE)) != NULL)))
836 {
837 /* Check <Type> value */
838 if ((tmp_node->children != NULL) && (tmp_node->children->type == WBXML_TREE_TEXT_NODE)) {
839 /* This function is used by wbxml and xml callbacks.
840 * So content types must be handled for both situations.
841 */
842
843 /* application/vnd.syncml-devinf+wbxml */
844 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "application/vnd.syncml-devinf+wbxml") == 0) {
845 return WBXML_SYNCML_DATA_TYPE_WBXML;
846 }
847
848 /* application/vnd.syncml-devinf+xml */
849 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "application/vnd.syncml-devinf+xml") == 0) {
850 return WBXML_SYNCML_DATA_TYPE_NORMAL;
851 }
852
853 /* application/vnd.syncml.dmtnds+wbxml */
854 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "application/vnd.syncml.dmtnds+wbxml") == 0) {
855 return WBXML_SYNCML_DATA_TYPE_WBXML;
856 }
857
858 /* application/vnd.syncml.dmtnds+xml */
859 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "application/vnd.syncml.dmtnds+xml") == 0) {
860 return WBXML_SYNCML_DATA_TYPE_NORMAL;
861 }
862
863 /* text/clear */
864 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "text/clear") == 0) {
865 return WBXML_SYNCML_DATA_TYPE_CLEAR;
866 }
867
868 /* text/directory;profile=vCard */
869 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "text/directory;profile=vCard") == 0) {
870 return WBXML_SYNCML_DATA_TYPE_DIRECTORY_VCARD;
871 }
872
873 /* text/x-vcard */
874 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "text/x-vcard") == 0) {
875 return WBXML_SYNCML_DATA_TYPE_VCARD;
876 }
877
878 /* text/x-vcalendar */
879 if (wbxml_buffer_compare_cstr(tmp_node->children->content, "text/x-vcalendar") == 0) {
880 return WBXML_SYNCML_DATA_TYPE_VCALENDAR;
881 }
882 }
883 }
884
885 /**
886 * Hack: we assume that any <Data> inside a <Replace> or <Add> Item is a vObject (vCard / vCal / ...).
887 *
888 * This is because when parsing a <Data> content we really need to put a CDATA, event if we don't really
889 * know the content-type. For example when receiving the end of a splitted vObject with Samsung D600, we receive this:
890 *
891 * <Replace>
892 * <CmdID>162</CmdID>
893 * <Item>
894 * <Source>
895 * <LocURI>./690</LocURI>
896 * </Source>
897 * <Data>EF;CELL:0661809055
898 * TEL;HOME:0299783886
899 * X-IRMC-LUID:690
900 * END:VCARD</Data>
901 * </Item>
902 * </Replace>
903 *
904 * There is no <Meta> info to find the content-type of the <Data>.
905 */
906 if ( (node->parent != NULL) &&
907 (node->parent->parent != NULL) &&
908 (node->parent->parent->name != NULL) &&
909 ((WBXML_STRCMP(wbxml_tag_get_xml_name(node->parent->parent->name), "Add") == 0) ||
910 (WBXML_STRCMP(wbxml_tag_get_xml_name(node->parent->parent->name), "Replace") == 0)) )
911 {
912 return WBXML_SYNCML_DATA_TYPE_VOBJECT;
913 }
914 }
915
916 return WBXML_SYNCML_DATA_TYPE_NORMAL;
917 }
918
919 #endif /* WBXML_SUPPORT_SYNCML */
920
921
wbxml_tree_node_have_child_elt(WBXMLTreeNode * node)922 WBXML_DECLARE(WB_BOOL) wbxml_tree_node_have_child_elt(WBXMLTreeNode *node)
923 {
924 WBXMLTreeNode *current = NULL;
925
926 if (node != NULL) {
927 /* Get first child */
928 current = node->children;
929
930 while (current != NULL) {
931 if (current->type == WBXML_TREE_ELEMENT_NODE) {
932 /* Element Node found ! */
933 return TRUE;
934 }
935
936 /* Check next child */
937 current = current->next;
938 }
939 }
940
941 return FALSE;
942 }
943
944
wbxml_tree_node_get_all_children(WBXMLTreeNode * node)945 WBXML_DECLARE(WBXMLList*) wbxml_tree_node_get_all_children(WBXMLTreeNode *node)
946 {
947 WBXMLList* result = NULL;
948
949 if ( node == NULL )
950 return NULL;
951
952 node = node->children;
953
954 while ( node != NULL ) {
955 /* Create result list if not already done */
956 if ( result == NULL )
957 result = wbxml_list_create();
958
959 /* Append node to result */
960 wbxml_list_append(result, node);
961
962 /* Go to next node */
963 node = node->next;
964 }
965
966 return result;
967 }
968
969
wbxml_tree_create(WBXMLLanguage lang,WBXMLCharsetMIBEnum orig_charset)970 WBXML_DECLARE(WBXMLTree *) wbxml_tree_create(WBXMLLanguage lang,
971 WBXMLCharsetMIBEnum orig_charset)
972 {
973 WBXMLTree *result = NULL;
974
975 if ((result = wbxml_malloc(sizeof(WBXMLTree))) == NULL)
976 return NULL;
977
978 result->lang = wbxml_tables_get_table(lang);
979 result->root = NULL;
980 result->orig_charset = orig_charset;
981 result->cur_code_page = 0;
982
983 return result;
984 }
985
986
wbxml_tree_destroy(WBXMLTree * tree)987 WBXML_DECLARE(void) wbxml_tree_destroy(WBXMLTree *tree)
988 {
989 if (tree != NULL) {
990 /* Destroy root node and all its children */
991 wbxml_tree_node_destroy_all(tree->root);
992
993 /* Free tree */
994 wbxml_free(tree);
995 }
996 }
997
998
999 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_node(WBXMLTree * tree,WBXMLTreeNode * parent,WBXMLTreeNode * node)1000 WBXML_DECLARE(WB_BOOL) wbxml_tree_add_node(WBXMLTree *tree, WBXMLTreeNode *parent, WBXMLTreeNode *node)
1001 {
1002 WBXMLTreeNode *tmp = NULL;
1003
1004 if ((tree == NULL) || (node == NULL))
1005 return FALSE;
1006
1007 /* Set parent to new node */
1008 node->parent = parent;
1009
1010 /* Check if this is the Root Element */
1011 if (parent != NULL) {
1012 /* This is not the Root Element... search for previous sibbling element */
1013 if (parent->children != NULL) {
1014 /* Add this Node to end of Sibbling Node list of Parent */
1015 tmp = parent->children;
1016
1017 /* !!! WARNING !!!
1018 * EXPAT splits <html> into three separate text nodes.
1019 * Therefore it is necessary to scan for splitted text nodes and
1020 * join them to get consistent text nodes.
1021 */
1022
1023 /* If the handled node is a text node and the last node is a text node
1024 * then the last node must be replace.
1025 * Otherwise the node will be appended.
1026 */
1027 while (tmp->next != NULL)
1028 tmp = tmp->next;
1029
1030 if (node->type == WBXML_TREE_TEXT_NODE &&
1031 tmp->type == WBXML_TREE_TEXT_NODE) {
1032
1033 /* join the two text nodes and replace the present text node */
1034 if (!wbxml_buffer_append(tmp->content, node->content))
1035 return FALSE;
1036
1037 if (tmp->prev == NULL) {
1038 /* tmp is first child */
1039 parent->children = node;
1040 } else {
1041 /* tmp is not first child */
1042 tmp->prev->next = node;
1043 node->prev = tmp->prev;
1044 }
1045
1046 wbxml_buffer_destroy(node->content);
1047 node->content = tmp->content;
1048 tmp->content = NULL;
1049 wbxml_tree_node_destroy(tmp);
1050 } else {
1051 /* normal situation => append node */
1052 node->prev = tmp;
1053 tmp->next = node;
1054 }
1055 }
1056 else {
1057 /* No previous sibbling element */
1058 parent->children = node;
1059 }
1060 }
1061 else {
1062 /* We do NOT allow replacement of an existing Tree Node */
1063 if (tree->root != NULL)
1064 return FALSE;
1065
1066 /* This is the Root Element */
1067 tree->root = node;
1068 }
1069
1070 return TRUE;
1071 }
1072
1073
1074 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_extract_node(WBXMLTree * tree,WBXMLTreeNode * node)1075 WBXML_DECLARE(WBXMLError) wbxml_tree_extract_node(WBXMLTree *tree,
1076 WBXMLTreeNode *node)
1077 {
1078 if ((tree == NULL) || (node == NULL))
1079 return WBXML_ERROR_BAD_PARAMETER;
1080
1081 /* Parent link */
1082 if (node->parent != NULL) {
1083 if (node->parent->children == node) {
1084 /* Update parent children */
1085 node->parent->children = node->next;
1086 }
1087
1088 /* No more parent */
1089 node->parent = NULL;
1090 }
1091 else {
1092 /* Root removed ! */
1093 tree->root = node->next;
1094 }
1095
1096 /* Link next node to previous node */
1097 if (node->next != NULL)
1098 node->next->prev = node->prev;
1099
1100 /* Link previous node to next node */
1101 if (node->prev != NULL)
1102 node->prev->next = node->next;
1103
1104 /* Cleanup pointers */
1105 node->next = node->prev = NULL;
1106
1107 return WBXML_OK;
1108 }
1109
1110
1111 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_elt(WBXMLTree * tree,WBXMLTreeNode * parent,WBXMLTag * tag)1112 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_elt(WBXMLTree *tree,
1113 WBXMLTreeNode *parent,
1114 WBXMLTag *tag)
1115 {
1116 WBXMLTreeNode *node = NULL;
1117
1118 /* Create a new Node */
1119 if ((node = wbxml_tree_node_create(WBXML_TREE_ELEMENT_NODE)) == NULL) {
1120 return NULL;
1121 }
1122
1123 /* Set Element */
1124 if ((node->name = wbxml_tag_duplicate(tag)) == NULL) {
1125 wbxml_tree_node_destroy(node);
1126 return NULL;
1127 }
1128
1129 /* Add this Node to Tree */
1130 if (!wbxml_tree_add_node(tree, parent, node)) {
1131 wbxml_tree_node_destroy(node);
1132 return NULL;
1133 }
1134
1135 return node;
1136 }
1137
1138
1139 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_elt_with_attrs(WBXMLTree * tree,WBXMLTreeNode * parent,WBXMLTag * tag,WBXMLAttribute ** attrs)1140 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_elt_with_attrs(WBXMLTree *tree,
1141 WBXMLTreeNode *parent,
1142 WBXMLTag *tag,
1143 WBXMLAttribute **attrs)
1144 {
1145 WBXMLTreeNode *node = NULL;
1146
1147 /* Add element */
1148 if ((node = wbxml_tree_add_elt(tree, parent, tag)) == NULL) {
1149 return NULL;
1150 }
1151
1152 /* Add attributes to element */
1153 if ((attrs != NULL) && (*attrs != NULL)) {
1154 if (wbxml_tree_node_add_attrs(node, attrs) != WBXML_OK) {
1155 /* Remove node from Tree */
1156 wbxml_tree_extract_node(tree, node);
1157 wbxml_tree_node_destroy(node);
1158 return NULL;
1159 }
1160 }
1161
1162 return node;
1163 }
1164
1165
1166 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_xml_elt(WBXMLTree * tree,WBXMLTreeNode * parent,WB_UTINY * name)1167 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_xml_elt(WBXMLTree *tree,
1168 WBXMLTreeNode *parent,
1169 WB_UTINY *name)
1170 {
1171 const WBXMLTagEntry *tag_entry = NULL;
1172 WBXMLTreeNode *node = NULL;
1173 WBXMLTag *tag = NULL;
1174 WB_UTINY *sep = NULL;
1175 const WB_UTINY *namespace_name = NULL;
1176 WB_UTINY *element_name = NULL;
1177
1178 /* Separate the namespace from the element name */
1179 sep = (WB_UTINY *)strrchr((const WB_TINY *) name, WBXML_NAMESPACE_SEPARATOR);
1180 if (sep != NULL) {
1181 /* Temporarily split the string by changing the separater to a null-terminator */
1182 *sep = '\0';
1183
1184 namespace_name = name;
1185 element_name = sep+1;
1186 }
1187 else {
1188 /* No namespace, so just set it to an empty string (specifically, the null-terminator at the end of the elemet name */
1189 namespace_name = name + strlen((const WB_TINY *) name);
1190 element_name = name;
1191 }
1192
1193 WBXML_DEBUG((WBXML_CONV, "Parsed element name: Namespace='%s', Element='%s'", namespace_name, element_name));
1194
1195 /* Update the current code page to match the one specified by the namespace */
1196 tree->cur_code_page = wbxml_tables_get_code_page(tree->lang->nsTable, (const WB_TINY *) namespace_name);
1197
1198 /* Search for XML Tag Name in Table */
1199 if ((tag_entry = wbxml_tables_get_tag_from_xml(tree->lang, tree->cur_code_page, element_name)) != NULL) {
1200 tree->cur_code_page = tag_entry->wbxmlCodePage;
1201
1202 /* Found : token tag */
1203 tag = wbxml_tag_create_token(tag_entry);
1204 }
1205 else {
1206 /* Not found : literal tag */
1207 tag = wbxml_tag_create_literal(element_name);
1208 }
1209
1210 if (sep != NULL) {
1211 /* We are done with the element and namespace names, so put the separator character back */
1212 *sep = WBXML_NAMESPACE_SEPARATOR;
1213 }
1214
1215 if (tag == NULL)
1216 return NULL;
1217
1218 /* Create a new Node */
1219 if ((node = wbxml_tree_node_create(WBXML_TREE_ELEMENT_NODE)) == NULL) {
1220 wbxml_tag_destroy(tag);
1221 return NULL;
1222 }
1223
1224 /* Set Node Tag */
1225 node->name = tag;
1226
1227 /* Add this Node to Tree */
1228 if (!wbxml_tree_add_node(tree, parent, node)) {
1229 wbxml_tree_node_destroy(node);
1230 return NULL;
1231 }
1232
1233 return node;
1234 }
1235
1236
1237 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_xml_elt_with_attrs(WBXMLTree * tree,WBXMLTreeNode * parent,WB_UTINY * name,const WB_UTINY ** attrs)1238 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_xml_elt_with_attrs(WBXMLTree *tree,
1239 WBXMLTreeNode *parent,
1240 WB_UTINY *name,
1241 const WB_UTINY **attrs)
1242 {
1243 WBXMLTreeNode *node = NULL;
1244
1245 /* Add element */
1246 if ((node = wbxml_tree_add_xml_elt(tree, parent, name)) == NULL) {
1247 return NULL;
1248 }
1249
1250 /* Add attributes to element */
1251 if ((attrs != NULL) && (*attrs != NULL)) {
1252 if (wbxml_tree_node_add_xml_attrs(tree->lang, node, attrs) != WBXML_OK) {
1253 /* Remove node from Tree */
1254 wbxml_tree_extract_node(tree, node);
1255 wbxml_tree_node_destroy(node);
1256 return NULL;
1257 }
1258 }
1259
1260 return node;
1261 }
1262
1263
1264 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_text(WBXMLTree * tree,WBXMLTreeNode * parent,const WB_UTINY * text,WB_ULONG len)1265 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_text(WBXMLTree *tree,
1266 WBXMLTreeNode *parent,
1267 const WB_UTINY *text,
1268 WB_ULONG len)
1269 {
1270 WBXMLTreeNode *node = NULL;
1271
1272 /* Create a new Node */
1273 if ((node = wbxml_tree_node_create(WBXML_TREE_TEXT_NODE)) == NULL) {
1274 return NULL;
1275 }
1276
1277 /* Set Content */
1278 if ((node->content = wbxml_buffer_create(text, len, len)) == NULL) {
1279 wbxml_tree_node_destroy(node);
1280 return NULL;
1281 }
1282
1283 /* Add this Node to Tree */
1284 if (!wbxml_tree_add_node(tree, parent, node)) {
1285 wbxml_tree_node_destroy(node);
1286 return NULL;
1287 }
1288
1289 return node;
1290 }
1291
1292
1293 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_cdata(WBXMLTree * tree,WBXMLTreeNode * parent)1294 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_cdata(WBXMLTree *tree,
1295 WBXMLTreeNode *parent)
1296 {
1297 WBXMLTreeNode *node = NULL;
1298
1299 /* Create a new Node */
1300 if ((node = wbxml_tree_node_create(WBXML_TREE_CDATA_NODE)) == NULL) {
1301 return NULL;
1302 }
1303
1304 /* Add this Node to Tree */
1305 if (!wbxml_tree_add_node(tree, parent, node)) {
1306 wbxml_tree_node_destroy(node);
1307 return NULL;
1308 }
1309
1310 return node;
1311 }
1312
1313
1314 /** @todo wbxml_tree_add_cdata_with_text() */
1315
1316
1317 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_tree(WBXMLTree * tree,WBXMLTreeNode * parent,WBXMLTree * new_tree)1318 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_tree(WBXMLTree *tree,
1319 WBXMLTreeNode *parent,
1320 WBXMLTree *new_tree)
1321 {
1322 WBXMLTreeNode *node = NULL;
1323
1324 /* Create a new Node */
1325 if ((node = wbxml_tree_node_create(WBXML_TREE_TREE_NODE)) == NULL) {
1326 return NULL;
1327 }
1328
1329 /* Add this Node to Tree */
1330 if (!wbxml_tree_add_node(tree, parent, node)) {
1331 wbxml_tree_node_destroy(node);
1332 return NULL;
1333 }
1334
1335 /* Set Tree */
1336 node->tree = new_tree;
1337
1338 return node;
1339 }
1340
1341
1342 /** @todo Rewrite this function (use wbxml_tree_node_* functions) */
wbxml_tree_add_xml_elt_with_attrs_and_text(WBXMLTree * tree,WBXMLTreeNode * parent,WB_UTINY * name,const WB_UTINY ** attrs,const WB_UTINY * text,WB_ULONG len)1343 WBXML_DECLARE(WBXMLTreeNode *) wbxml_tree_add_xml_elt_with_attrs_and_text(WBXMLTree *tree,
1344 WBXMLTreeNode *parent,
1345 WB_UTINY *name,
1346 const WB_UTINY **attrs,
1347 const WB_UTINY *text,
1348 WB_ULONG len)
1349 {
1350 WBXMLTreeNode *new_node = NULL;
1351
1352 /* Add XML node */
1353 if ((new_node = wbxml_tree_add_xml_elt_with_attrs(tree, parent, name, attrs)) == NULL)
1354 return NULL;
1355
1356 /* Add text node */
1357 if ((text != NULL) && (len > 0)) {
1358 if (wbxml_tree_add_text(tree, new_node, text, len) == NULL) {
1359 wbxml_tree_node_destroy(new_node);
1360 return NULL;
1361 }
1362 }
1363
1364 return new_node;
1365 }
1366