1 /*******************************************************************************
2 *
3 * Copyright (c) 2000-2003 Intel Corporation
4 * All rights reserved.
5 * Copyright (c) 2012 France Telecom All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 * - Neither name of Intel Corporation nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
27 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 ******************************************************************************/
32
33
34 /*!
35 * \file
36 */
37
38
39 #include "ixmlparser.h"
40
41
42 #include <assert.h>
43 #include <stdlib.h> /* for free() */
44 #include <string.h>
45
46
ixmlElement_init(IXML_Element * element)47 void ixmlElement_init(IXML_Element *element)
48 {
49 if (element != NULL) {
50 memset(element, 0, sizeof (IXML_Element));
51 }
52 }
53
ixmlElement_getTagName(IXML_Element * element)54 const DOMString ixmlElement_getTagName(IXML_Element *element)
55 {
56 if( element != NULL ) {
57 return element->tagName;
58 } else {
59 return NULL;
60 }
61 }
62
63
ixmlElement_setTagName(IXML_Element * element,const char * tagName)64 int ixmlElement_setTagName(IXML_Element *element, const char *tagName)
65 {
66 int rc = IXML_SUCCESS;
67
68 assert(element != NULL && tagName != NULL);
69
70 if (element == NULL || tagName == NULL) {
71 return IXML_FAILED;
72 }
73
74 if (element->tagName != NULL) {
75 free(element->tagName);
76 }
77 element->tagName = strdup(tagName);
78 if (element->tagName == NULL) {
79 rc = IXML_INSUFFICIENT_MEMORY;
80 }
81
82 return rc;
83 }
84
85
ixmlElement_getAttribute(IXML_Element * element,const DOMString name)86 const DOMString ixmlElement_getAttribute(IXML_Element *element, const DOMString name)
87 {
88 IXML_Node *attrNode;
89
90 if (element == NULL || name == NULL) {
91 return NULL;
92 }
93
94 attrNode = element->n.firstAttr;
95 while (attrNode != NULL) {
96 if (strcmp(attrNode->nodeName, name) == 0) {
97 return attrNode->nodeValue;
98 } else {
99 attrNode = attrNode->nextSibling;
100 }
101 }
102
103 return NULL;
104 }
105
106
ixmlElement_setAttribute(IXML_Element * element,const DOMString name,const DOMString value)107 int ixmlElement_setAttribute(
108 IXML_Element *element,
109 const DOMString name,
110 const DOMString value)
111 {
112 IXML_Node *attrNode;
113 IXML_Attr *newAttrNode;
114 int errCode = IXML_SUCCESS;
115
116 if (element == NULL || name == NULL || value == NULL) {
117 errCode = IXML_INVALID_PARAMETER;
118 goto ErrorHandler;
119 }
120
121 if (Parser_isValidXmlName(name) == 0) {
122 errCode = IXML_INVALID_CHARACTER_ERR;
123 goto ErrorHandler;
124 }
125
126 attrNode = element->n.firstAttr;
127 while (attrNode != NULL) {
128 if (strcmp(attrNode->nodeName, name) == 0) {
129 /* Found it */
130 break;
131 } else {
132 attrNode = attrNode->nextSibling;
133 }
134 }
135
136 if (attrNode == NULL) {
137 /* Add a new attribute */
138 errCode = ixmlDocument_createAttributeEx(
139 (IXML_Document *)element->n.ownerDocument, name, &newAttrNode);
140 if (errCode != IXML_SUCCESS) {
141 goto ErrorHandler;
142 }
143
144 attrNode = (IXML_Node *)newAttrNode;
145 attrNode->nodeValue = strdup(value);
146 if (attrNode->nodeValue == NULL) {
147 ixmlAttr_free(newAttrNode);
148 errCode = IXML_INSUFFICIENT_MEMORY;
149 goto ErrorHandler;
150 }
151
152 errCode = ixmlElement_setAttributeNode(element, newAttrNode, NULL);
153 if (errCode != IXML_SUCCESS) {
154 ixmlAttr_free(newAttrNode);
155 goto ErrorHandler;
156 }
157 } else {
158 if (attrNode->nodeValue != NULL) {
159 /* Attribute name has a value already */
160 free(attrNode->nodeValue);
161 }
162 attrNode->nodeValue = strdup(value);
163 if (attrNode->nodeValue == NULL) {
164 errCode = IXML_INSUFFICIENT_MEMORY;
165 }
166 }
167
168 ErrorHandler:
169 return errCode;
170 }
171
172
ixmlElement_removeAttribute(IXML_Element * element,const DOMString name)173 int ixmlElement_removeAttribute(IXML_Element *element, const DOMString name)
174 {
175 IXML_Node *attrNode;
176
177 if (element == NULL || name == NULL) {
178 return IXML_INVALID_PARAMETER;
179 }
180
181 attrNode = element->n.firstAttr;
182 while (attrNode != NULL) {
183 if (strcmp(attrNode->nodeName, name) == 0) {
184 /* Found it */
185 break;
186 } else {
187 attrNode = attrNode->nextSibling;
188 }
189 }
190 if (attrNode != NULL) {
191 /* Has the attribute */
192 if (attrNode->nodeValue != NULL) {
193 free(attrNode->nodeValue);
194 attrNode->nodeValue = NULL;
195 }
196 }
197
198 return IXML_SUCCESS;
199 }
200
201
ixmlElement_getAttributeNode(IXML_Element * element,const DOMString name)202 IXML_Attr *ixmlElement_getAttributeNode(IXML_Element *element, const DOMString name)
203 {
204 IXML_Node *attrNode;
205
206 if (element == NULL || name == NULL) {
207 return NULL;
208 }
209
210 attrNode = element->n.firstAttr;
211 while (attrNode != NULL) {
212 if (strcmp(attrNode->nodeName, name) == 0) {
213 /* found it */
214 break;
215 } else {
216 attrNode = attrNode->nextSibling;
217 }
218 }
219
220 return (IXML_Attr *)attrNode;
221 }
222
223
ixmlElement_setAttributeNode(IXML_Element * element,IXML_Attr * newAttr,IXML_Attr ** rtAttr)224 int ixmlElement_setAttributeNode(
225 IXML_Element *element,
226 IXML_Attr *newAttr,
227 IXML_Attr **rtAttr)
228 {
229 IXML_Node *attrNode = NULL;
230 IXML_Node *node = NULL;
231 IXML_Node *nextAttr = NULL;
232 IXML_Node *prevAttr = NULL;
233 IXML_Node *preSib = NULL;
234 IXML_Node *nextSib = NULL;
235
236 if (!element || !newAttr)
237 return IXML_INVALID_PARAMETER;
238 if (newAttr->n.ownerDocument != element->n.ownerDocument)
239 return IXML_WRONG_DOCUMENT_ERR;
240 if (newAttr->ownerElement)
241 return IXML_INUSE_ATTRIBUTE_ERR;
242 newAttr->ownerElement = element;
243 node = (IXML_Node *)newAttr;
244 attrNode = element->n.firstAttr;
245 while (attrNode) {
246 if (!strcmp(attrNode->nodeName, node->nodeName))
247 /* Found it */
248 break;
249 else
250 attrNode = attrNode->nextSibling;
251 }
252 if (attrNode) {
253 /* Already present, will replace by newAttr */
254 preSib = attrNode->prevSibling;
255 nextSib = attrNode->nextSibling;
256 if (preSib)
257 preSib->nextSibling = node;
258 if (nextSib)
259 nextSib->prevSibling = node;
260 if (element->n.firstAttr == attrNode)
261 element->n.firstAttr = node;
262 if (rtAttr)
263 *rtAttr = (IXML_Attr *)attrNode;
264 else
265 ixmlAttr_free((IXML_Attr *)attrNode);
266 } else {
267 /* Add this attribute */
268 if (element->n.firstAttr) {
269 prevAttr = element->n.firstAttr;
270 nextAttr = prevAttr->nextSibling;
271 while (nextAttr) {
272 prevAttr = nextAttr;
273 nextAttr = prevAttr->nextSibling;
274 }
275 prevAttr->nextSibling = node;
276 node->prevSibling = prevAttr;
277 } else {
278 /* This is the first attribute node */
279 element->n.firstAttr = node;
280 node->prevSibling = NULL;
281 node->nextSibling = NULL;
282 }
283 if (rtAttr)
284 *rtAttr = NULL;
285 }
286
287 return IXML_SUCCESS;
288 }
289
290 /*!
291 * \brief Find a attribute node whose contents are the same as the oldAttr.
292 *
293 * \return If found, the attribute node is returned, otherwise \b NULL is
294 * returned.
295 */
ixmlElement_findAttributeNode(IXML_Element * element,IXML_Attr * oldAttr)296 static IXML_Node *ixmlElement_findAttributeNode(
297 /*! [in] The element to search for the attribute. */
298 IXML_Element *element,
299 /*! [in] The attribute node to match. */
300 IXML_Attr *oldAttr)
301 {
302 IXML_Node *attrNode;
303 IXML_Node *oldAttrNode = (IXML_Node *)oldAttr;
304
305 assert(element != NULL && oldAttr != NULL);
306
307 attrNode = element->n.firstAttr;
308 while (attrNode != NULL) {
309 /* parentNode, prevSib, nextSib and ownerDocument doesn't matter */
310 if (ixmlNode_compare(attrNode, oldAttrNode) == 1) {
311 /* Found it */
312 break;
313 } else {
314 attrNode = attrNode->nextSibling;
315 }
316 }
317
318 return attrNode;
319 }
320
321
ixmlElement_removeAttributeNode(IXML_Element * element,IXML_Attr * oldAttr,IXML_Attr ** rtAttr)322 int ixmlElement_removeAttributeNode(
323 IXML_Element *element,
324 IXML_Attr *oldAttr,
325 IXML_Attr **rtAttr)
326 {
327 IXML_Node *attrNode;
328 IXML_Node *preSib;
329 IXML_Node *nextSib;
330
331 if(element == NULL || oldAttr == NULL) {
332 return IXML_INVALID_PARAMETER;
333 }
334
335 attrNode = ixmlElement_findAttributeNode( element, oldAttr );
336 if (attrNode != NULL) {
337 /* Has the attribute */
338 preSib = attrNode->prevSibling;
339 nextSib = attrNode->nextSibling;
340 if (preSib != NULL) {
341 preSib->nextSibling = nextSib;
342 }
343 if (nextSib != NULL) {
344 nextSib->prevSibling = preSib;
345 }
346 if (element->n.firstAttr == attrNode) {
347 element->n.firstAttr = nextSib;
348 }
349 attrNode->parentNode = NULL;
350 attrNode->prevSibling = NULL;
351 attrNode->nextSibling = NULL;
352 *rtAttr = (IXML_Attr *)attrNode;
353 return IXML_SUCCESS;
354 } else {
355 return IXML_NOT_FOUND_ERR;
356 }
357 }
358
359
ixmlElement_getElementsByTagName(IXML_Element * element,const DOMString tagName)360 IXML_NodeList *ixmlElement_getElementsByTagName(
361 IXML_Element *element,
362 const DOMString tagName)
363 {
364 IXML_NodeList *returnNodeList = NULL;
365
366 if (element != NULL && tagName != NULL) {
367 ixmlNode_getElementsByTagName(
368 (IXML_Node *)element, tagName, &returnNodeList);
369 }
370 return returnNodeList;
371 }
372
373
ixmlElement_getAttributeNS(IXML_Element * element,const DOMString namespaceURI,const DOMString localName)374 const DOMString ixmlElement_getAttributeNS(
375 /* IN */ IXML_Element *element,
376 /* IN */ const DOMString namespaceURI,
377 /* IN */ const DOMString localName)
378 {
379 IXML_Node *attrNode;
380
381 if (element == NULL || namespaceURI == NULL || localName == NULL) {
382 return NULL;
383 }
384
385 attrNode = element->n.firstAttr;
386 while (attrNode != NULL) {
387 if (strcmp(attrNode->localName, localName) == 0 &&
388 strcmp(attrNode->namespaceURI, namespaceURI) == 0) {
389 /* Found it */
390 return attrNode->nodeValue;
391 } else {
392 attrNode = attrNode->nextSibling;
393 }
394 }
395
396 return NULL;
397 }
398
399
ixmlElement_setAttributeNS(IXML_Element * element,const DOMString namespaceURI,const DOMString qualifiedName,const DOMString value)400 int ixmlElement_setAttributeNS(
401 IXML_Element *element,
402 const DOMString namespaceURI,
403 const DOMString qualifiedName,
404 const DOMString value)
405 {
406 IXML_Node *attrNode = NULL;
407 IXML_Node newAttrNode;
408 IXML_Attr *newAttr;
409 int rc;
410
411 if (element == NULL || namespaceURI == NULL || qualifiedName == NULL ||
412 value == NULL) {
413 return IXML_INVALID_PARAMETER;
414 }
415
416 if (Parser_isValidXmlName(qualifiedName) == 0) {
417 return IXML_INVALID_CHARACTER_ERR;
418 }
419
420 ixmlNode_init(&newAttrNode);
421 newAttrNode.nodeName = strdup(qualifiedName);
422 if (newAttrNode.nodeName == NULL) {
423 return IXML_INSUFFICIENT_MEMORY;
424 }
425
426 rc = Parser_setNodePrefixAndLocalName(&newAttrNode);
427 if (rc != IXML_SUCCESS) {
428 Parser_freeNodeContent(&newAttrNode);
429 return rc;
430 }
431
432 /* see DOM 2 spec page 59 */
433 if ((newAttrNode.prefix != NULL && namespaceURI == NULL) ||
434 (newAttrNode.prefix != NULL && strcmp(newAttrNode.prefix, "xml") == 0 &&
435 strcmp(namespaceURI, "http://www.w3.org/XML/1998/namespace") != 0) ||
436 (strcmp(qualifiedName, "xmlns") == 0 &&
437 strcmp(namespaceURI, "http://www.w3.org/2000/xmlns/") != 0)) {
438 Parser_freeNodeContent( &newAttrNode );
439 return IXML_NAMESPACE_ERR;
440 }
441
442 attrNode = element->n.firstAttr;
443 while (attrNode != NULL) {
444 if (strcmp(attrNode->localName, newAttrNode.localName) == 0 &&
445 strcmp(attrNode->namespaceURI, namespaceURI) == 0) {
446 /* Found it */
447 break;
448 } else {
449 attrNode = attrNode->nextSibling;
450 }
451 }
452 if (attrNode != NULL) {
453 if (attrNode->prefix != NULL) {
454 /* Remove the old prefix */
455 free(attrNode->prefix);
456 }
457 /* replace it with the new prefix */
458 if (newAttrNode.prefix != NULL) {
459 attrNode->prefix = strdup( newAttrNode.prefix );
460 if (attrNode->prefix == NULL) {
461 Parser_freeNodeContent(&newAttrNode);
462 return IXML_INSUFFICIENT_MEMORY;
463 }
464 } else
465 attrNode->prefix = newAttrNode.prefix;
466
467 if (attrNode->nodeValue != NULL) {
468 free(attrNode->nodeValue);
469 }
470 attrNode->nodeValue = strdup(value);
471 if (attrNode->nodeValue == NULL) {
472 free(attrNode->prefix);
473 Parser_freeNodeContent(&newAttrNode);
474 return IXML_INSUFFICIENT_MEMORY;
475 }
476 } else {
477 /* Add a new attribute */
478 rc = ixmlDocument_createAttributeNSEx(
479 (IXML_Document *)element->n.ownerDocument,
480 namespaceURI,
481 qualifiedName,
482 &newAttr);
483 if (rc != IXML_SUCCESS) {
484 Parser_freeNodeContent(&newAttrNode);
485 return rc;
486 }
487 newAttr->n.nodeValue = strdup(value);
488 if (newAttr->n.nodeValue == NULL) {
489 ixmlAttr_free(newAttr);
490 Parser_freeNodeContent(&newAttrNode);
491 return IXML_INSUFFICIENT_MEMORY;
492 }
493 if (ixmlElement_setAttributeNodeNS(element, newAttr, &newAttr) != IXML_SUCCESS) {
494 ixmlAttr_free(newAttr);
495 Parser_freeNodeContent(&newAttrNode);
496 return IXML_FAILED;
497 }
498 }
499 Parser_freeNodeContent(&newAttrNode);
500
501 return IXML_SUCCESS;
502 }
503
504
ixmlElement_removeAttributeNS(IXML_Element * element,const DOMString namespaceURI,const DOMString localName)505 int ixmlElement_removeAttributeNS(
506 IXML_Element *element,
507 const DOMString namespaceURI,
508 const DOMString localName)
509 {
510 IXML_Node *attrNode = NULL;
511
512 if (element == NULL || namespaceURI == NULL || localName == NULL) {
513 return IXML_INVALID_PARAMETER;
514 }
515
516 attrNode = element->n.firstAttr;
517 while (attrNode != NULL) {
518 if (strcmp(attrNode->localName, localName) == 0 &&
519 strcmp(attrNode->namespaceURI, namespaceURI) == 0) {
520 /* Found it */
521 break;
522 } else {
523 attrNode = attrNode->nextSibling;
524 }
525 }
526 if(attrNode != NULL) {
527 /* Has the attribute */
528 if(attrNode->nodeValue != NULL) {
529 free(attrNode->nodeValue);
530 attrNode->nodeValue = NULL;
531 }
532 }
533
534 return IXML_SUCCESS;
535 }
536
537
ixmlElement_getAttributeNodeNS(IXML_Element * element,const DOMString namespaceURI,const DOMString localName)538 IXML_Attr *ixmlElement_getAttributeNodeNS(
539 IXML_Element *element,
540 const DOMString namespaceURI,
541 const DOMString localName)
542 {
543 IXML_Node *attrNode = NULL;
544
545 if (element == NULL || namespaceURI == NULL || localName == NULL) {
546 return NULL;
547 }
548
549 attrNode = element->n.firstAttr;
550 while (attrNode != NULL) {
551 if (strcmp(attrNode->localName, localName) == 0 &&
552 strcmp(attrNode->namespaceURI, namespaceURI) == 0) {
553 /* found it */
554 break;
555 } else {
556 attrNode = attrNode->nextSibling;
557 }
558 }
559
560 return (IXML_Attr *)attrNode;
561 }
562
563
ixmlElement_setAttributeNodeNS(IXML_Element * element,IXML_Attr * newAttr,IXML_Attr ** rtAttr)564 int ixmlElement_setAttributeNodeNS(
565 /* IN */ IXML_Element *element,
566 /* IN */ IXML_Attr *newAttr,
567 /* OUT */ IXML_Attr **rtAttr)
568 {
569 IXML_Node *attrNode = NULL;
570 IXML_Node *node = NULL;
571 IXML_Node *prevAttr = NULL;
572 IXML_Node *nextAttr = NULL;
573 IXML_Node *preSib = NULL;
574 IXML_Node *nextSib = NULL;
575
576 if (element == NULL || newAttr == NULL) {
577 return IXML_INVALID_PARAMETER;
578 }
579
580 if (newAttr->n.ownerDocument != element->n.ownerDocument) {
581 return IXML_WRONG_DOCUMENT_ERR;
582 }
583
584 if (newAttr->ownerElement != NULL && newAttr->ownerElement != element) {
585 return IXML_INUSE_ATTRIBUTE_ERR;
586 }
587
588 newAttr->ownerElement = element;
589 node = (IXML_Node *)newAttr;
590 attrNode = element->n.firstAttr;
591 while (attrNode != NULL) {
592 if (strcmp(attrNode->localName, node->localName) == 0 &&
593 strcmp(attrNode->namespaceURI, node->namespaceURI) == 0) {
594 /* Found it */
595 break;
596 } else {
597 attrNode = attrNode->nextSibling;
598 }
599 }
600 if (attrNode != NULL) {
601 /* already present, will replace by newAttr */
602 preSib = attrNode->prevSibling;
603 nextSib = attrNode->nextSibling;
604 if (preSib != NULL) {
605 preSib->nextSibling = node;
606 }
607 if (nextSib != NULL) {
608 nextSib->prevSibling = node;
609 }
610 if (element->n.firstAttr == attrNode) {
611 element->n.firstAttr = node;
612 }
613 *rtAttr = (IXML_Attr *)attrNode;
614
615 } else {
616 /* Add this attribute */
617 if (element->n.firstAttr != NULL) {
618 /* Element has attribute already */
619 prevAttr = element->n.firstAttr;
620 nextAttr = prevAttr->nextSibling;
621 while (nextAttr != NULL) {
622 prevAttr = nextAttr;
623 nextAttr = prevAttr->nextSibling;
624 }
625 prevAttr->nextSibling = node;
626 } else {
627 /* This is the first attribute node */
628 element->n.firstAttr = node;
629 node->prevSibling = NULL;
630 node->nextSibling = NULL;
631 }
632 if (rtAttr != NULL) {
633 *rtAttr = NULL;
634 }
635 }
636
637 return IXML_SUCCESS;
638 }
639
640
ixmlElement_getElementsByTagNameNS(IXML_Element * element,const DOMString namespaceURI,const DOMString localName)641 IXML_NodeList *ixmlElement_getElementsByTagNameNS(
642 IXML_Element *element,
643 const DOMString namespaceURI,
644 const DOMString localName)
645 {
646 IXML_Node *node = (IXML_Node *)element;
647 IXML_NodeList *nodeList = NULL;
648
649 if(element != NULL && namespaceURI != NULL && localName != NULL) {
650 ixmlNode_getElementsByTagNameNS(
651 node, namespaceURI, localName, &nodeList);
652 }
653
654 return nodeList;
655 }
656
657
ixmlElement_hasAttribute(IXML_Element * element,const DOMString name)658 int ixmlElement_hasAttribute(
659 IXML_Element *element,
660 const DOMString name)
661 {
662 IXML_Node *attrNode = NULL;
663
664 if (element == NULL || name == NULL) {
665 return 0;
666 }
667
668 attrNode = element->n.firstAttr;
669 while (attrNode != NULL) {
670 if (strcmp(attrNode->nodeName, name) == 0) {
671 return 1;
672 } else {
673 attrNode = attrNode->nextSibling;
674 }
675 }
676
677 return 0;
678 }
679
680
ixmlElement_hasAttributeNS(IXML_Element * element,const DOMString namespaceURI,const DOMString localName)681 int ixmlElement_hasAttributeNS(
682 IXML_Element * element,
683 const DOMString namespaceURI,
684 const DOMString localName )
685 {
686 IXML_Node *attrNode = NULL;
687
688 if (element == NULL || namespaceURI == NULL || localName == NULL) {
689 return 0;
690 }
691
692 attrNode = element->n.firstAttr;
693 while (attrNode != NULL) {
694 if (strcmp(attrNode->localName, localName) == 0 &&
695 strcmp(attrNode->namespaceURI, namespaceURI) == 0) {
696 return 1;
697 } else {
698 attrNode = attrNode->nextSibling;
699 }
700 }
701
702 return 0;
703 }
704
705
ixmlElement_free(IXML_Element * element)706 void ixmlElement_free(IXML_Element *element)
707 {
708 if (element != NULL) {
709 ixmlNode_free((IXML_Node *)element);
710 }
711 }
712
713