UPnPsdk 0.1
Universal Plug and Play +, Software Development Kit
 
Loading...
Searching...
No Matches
node.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 *
3 * Copyright (c) 2000-2003 Intel Corporation
4 * All rights reserved.
5 * Copyright (c) 2012 France Telecom All rights reserved.
6 * Copyright (C) 2022+ GPL 3 and higher by Ingo Höft, <Ingo@Hoeft-online.de>
7 * Redistribution only with this Copyright remark. Last modified: 2026-03-31
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * - Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 * - Neither name of Intel Corporation nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
29 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 ******************************************************************************/
34// Last compare with ./Pupnp source file, based on 2026-03-16, ver 1.14.30
39#include <ixml/ixmlparser.hpp>
40
41#include <cassert>
42// #include <stdlib.h> /* for free(), malloc() */
43#include <cstring>
44
45// #include "posix_overwrites.hpp" // IWYU pragma: keep
46
47void ixmlNode_init(IXML_Node* nodeptr) {
48 assert(nodeptr);
49
50 memset(nodeptr, 0, sizeof(IXML_Node));
51}
52
54 memset(nodeptr, 0, sizeof(IXML_CDATASection));
55}
56
58 if (nodeptr) {
59 ixmlNode_free((IXML_Node*)nodeptr);
60 }
61}
62
68 IXML_Node* nodeptr) {
69 IXML_Element* element = NULL;
70
71 if (nodeptr) {
72 if (nodeptr->nodeName) {
73 free(nodeptr->nodeName);
74 }
75 if (nodeptr->nodeValue) {
76 free(nodeptr->nodeValue);
77 }
78 if (nodeptr->namespaceURI) {
79 free(nodeptr->namespaceURI);
80 }
81 if (nodeptr->prefix) {
82 free(nodeptr->prefix);
83 }
84 if (nodeptr->localName) {
85 free(nodeptr->localName);
86 }
87 switch (nodeptr->nodeType) {
88 case eELEMENT_NODE:
89 element = (IXML_Element*)nodeptr;
90 free(element->tagName);
91 break;
92 default:
93 break;
94 }
95 free(nodeptr);
96 }
97}
98
99#if 0
100/*
101 * Old implementation of ixmlNode_free(). Due to its recursive nature, it was
102 * susceptible to attacks overflowing the stack.
103 *
104 * void ixmlNode_free(IXML_Node *nodeptr)
105 */
106void ixmlNode_recursive_free(IXML_Node *nodeptr)
107{
108 if (nodeptr) {
109#ifdef IXML_HAVE_SCRIPTSUPPORT
110 IXML_BeforeFreeNode_t handler = Parser_getBeforeFree();
111 if (handler) handler(nodeptr);
112#endif
113 ixmlNode_free(nodeptr->firstChild);
114 ixmlNode_free(nodeptr->nextSibling);
115 ixmlNode_free(nodeptr->firstAttr);
117 }
118}
119#endif
120
121/*
122 * void ixmlNode_non_recursive_free(IXML_Node *nodeptr)
123 */
124void ixmlNode_free(IXML_Node* nodeptr) {
125 IXML_Node* curr_child;
126 IXML_Node* prev_child;
127 IXML_Node* next_child;
128 IXML_Node* curr_attr;
129 IXML_Node* next_attr;
130
131 if (nodeptr) {
132#ifdef IXML_HAVE_SCRIPTSUPPORT
133 IXML_BeforeFreeNode_t handler = Parser_getBeforeFree();
134#endif
135 prev_child = nodeptr;
136 next_child = nodeptr->firstChild;
137 do {
138 curr_child = next_child;
139 do {
140 while (curr_child) {
141 prev_child = curr_child;
142 curr_child = curr_child->firstChild;
143 }
144 curr_child = prev_child;
145 while (curr_child) {
146 prev_child = curr_child;
147 curr_child = curr_child->nextSibling;
148 }
149 curr_child = prev_child;
150 next_child = curr_child->firstChild;
151 } while (next_child);
152 /* current is now the last sibling of the last child. */
153 /* Delete the attribute nodes of this child */
154 /* Attribute nodes only have siblings. */
155 curr_attr = curr_child->firstAttr;
156 while (curr_attr) {
157 next_attr = curr_attr->nextSibling;
158 ixmlNode_freeSingleNode(curr_attr);
159 curr_attr = next_attr;
160 }
161 curr_child->firstAttr = 0;
162 /* Return */
163 if (curr_child != nodeptr) {
164 if (curr_child->prevSibling) {
165 next_child = curr_child->prevSibling;
166 next_child->nextSibling = 0;
167 } else {
168 next_child = curr_child->parentNode;
169 next_child->firstChild = 0;
170 }
171 }
172#ifdef IXML_HAVE_SCRIPTSUPPORT
173 if (handler) {
174 handler(curr_child);
175 }
176#endif
177 ixmlNode_freeSingleNode(curr_child);
178 } while (curr_child != nodeptr);
179 }
180}
181
183 if (nodeptr) {
184 return nodeptr->nodeName;
185 }
186
187 return NULL;
188}
189
191 if (nodeptr) {
192 return nodeptr->localName;
193 }
194
195 return NULL;
196}
197
203 IXML_Node* nodeptr,
205 const char* namespaceURI) {
206 if (!nodeptr) {
207 return IXML_INVALID_PARAMETER;
208 }
209 if (nodeptr->namespaceURI) {
210 free(nodeptr->namespaceURI);
211 nodeptr->namespaceURI = NULL;
212 }
213 if (namespaceURI) {
214 nodeptr->namespaceURI = strdup(namespaceURI);
215 if (!nodeptr->namespaceURI) {
216 return IXML_INSUFFICIENT_MEMORY;
217 }
218 }
219
220 return IXML_SUCCESS;
221}
222
228 IXML_Node* nodeptr,
230 const char* prefix) {
231 if (!nodeptr) {
232 return IXML_INVALID_PARAMETER;
233 }
234 if (nodeptr->prefix) {
235 free(nodeptr->prefix);
236 nodeptr->prefix = NULL;
237 }
238 if (prefix) {
239 nodeptr->prefix = strdup(prefix);
240 if (!nodeptr->prefix) {
241 return IXML_INSUFFICIENT_MEMORY;
242 }
243 }
244
245 return IXML_SUCCESS;
246}
247
255 IXML_Node* nodeptr,
257 const char* localName) {
258 assert(nodeptr);
259
260 if (nodeptr->localName) {
261 free(nodeptr->localName);
262 nodeptr->localName = NULL;
263 }
264 if (localName) {
265 nodeptr->localName = strdup(localName);
266 if (!nodeptr->localName) {
267 return IXML_INSUFFICIENT_MEMORY;
268 }
269 }
270
271 return IXML_SUCCESS;
272}
273
275 DOMString retNamespaceURI = NULL;
276
277 if (nodeptr) {
278 retNamespaceURI = nodeptr->namespaceURI;
279 }
280
281 return retNamespaceURI;
282}
283
285 const DOMString prefix = NULL;
286
287 if (nodeptr) {
288 prefix = nodeptr->prefix;
289 }
290
291 return prefix;
292}
293
295 if (nodeptr) {
296 return nodeptr->nodeValue;
297 }
298
299 return NULL;
300}
301
302int ixmlNode_setNodeValue(IXML_Node* nodeptr, const char* newNodeValue) {
303 int rc = IXML_SUCCESS;
304
305 if (!nodeptr) {
306 return IXML_INVALID_PARAMETER;
307 }
308 if (nodeptr->nodeValue) {
309 free(nodeptr->nodeValue);
310 nodeptr->nodeValue = NULL;
311 }
312 if (newNodeValue) {
313 nodeptr->nodeValue = strdup(newNodeValue);
314 if (!nodeptr->nodeValue) {
315 return IXML_INSUFFICIENT_MEMORY;
316 }
317 }
318
319 return rc;
320}
321
322unsigned short ixmlNode_getNodeType(IXML_Node* nodeptr) {
323 if (nodeptr) {
324 return (unsigned short)nodeptr->nodeType;
325 } else {
326 return (unsigned short)eINVALID_NODE;
327 }
328}
329
331 if (nodeptr) {
332 return nodeptr->parentNode;
333 } else {
334 return NULL;
335 }
336}
337
339 if (nodeptr) {
340 return nodeptr->firstChild;
341 } else {
342 return NULL;
343 }
344}
345
347 IXML_Node* prev;
348 IXML_Node* next;
349
350 if (nodeptr) {
351 prev = nodeptr;
352 next = nodeptr->firstChild;
353 while (next) {
354 prev = next;
355 next = next->nextSibling;
356 }
357 return prev;
358 } else {
359 return NULL;
360 }
361}
362
364 if (nodeptr) {
365 return nodeptr->prevSibling;
366 } else {
367 return NULL;
368 }
369}
370
372 if (nodeptr) {
373 return nodeptr->nextSibling;
374 } else {
375 return NULL;
376 }
377}
378
380 if (nodeptr) {
381 return (IXML_Document*)nodeptr->ownerDocument;
382 } else {
383 return NULL;
384 }
385}
386
394 IXML_Node* ancestorNode,
396 IXML_Node* toFind) {
397 int found = 0;
398
399 if (ancestorNode && toFind) {
400 if (toFind->parentNode == ancestorNode) {
401 return 1;
402 } else {
403 found = ixmlNode_isAncestor(ancestorNode->firstChild, toFind);
404 if (found == 0) {
405 found = ixmlNode_isAncestor(ancestorNode->nextSibling, toFind);
406 }
407 }
408 }
409
410 return found;
411}
412
420 IXML_Node* nodeptr,
422 IXML_Node* toFind) {
423 int found = 0;
424
425 assert(nodeptr && toFind);
426
427 if (nodeptr && toFind) {
428 found = toFind->parentNode == nodeptr;
429 }
430
431 return found;
432}
433
443 IXML_Node* nodeptr,
445 IXML_Node* newChild) {
446 assert(nodeptr && newChild);
447
448 switch (nodeptr->nodeType) {
449 case eATTRIBUTE_NODE:
450 case eTEXT_NODE:
451 case eCDATA_SECTION_NODE:
452 return 0;
453 case eELEMENT_NODE:
454 switch (newChild->nodeType) {
455 case eATTRIBUTE_NODE:
456 case eDOCUMENT_NODE:
457 return 0;
458 default:
459 break;
460 }
461 break;
462 case eDOCUMENT_NODE:
463 switch (newChild->nodeType) {
464 case eELEMENT_NODE:
465 break;
466 default:
467 return 0;
468 }
469 break;
470 default:
471 break;
472 }
473
474 return 1;
475}
476
487 const IXML_Node* srcNode,
489 const IXML_Node* destNode) {
490 assert(srcNode && destNode);
491
492 /* clang-format off */
493 return srcNode == destNode ||
494 (strcmp(srcNode->nodeName, destNode->nodeName) == 0 &&
495 strcmp(srcNode->nodeValue, destNode->nodeValue) == 0 &&
496 srcNode->nodeType == destNode->nodeType &&
497 strcmp(srcNode->namespaceURI, destNode->namespaceURI) == 0 &&
498 strcmp(srcNode->prefix, destNode->prefix) == 0 &&
499 strcmp(srcNode->localName, destNode->localName) == 0);
500 /* clang-format on */
501}
502
504 IXML_Node* refChild) {
505 int ret = IXML_SUCCESS;
506
507 if (!nodeptr || !newChild) {
508 return IXML_INVALID_PARAMETER;
509 }
510 /* whether nodeptr allow children of the type of newChild */
511 if (ixmlNode_allowChildren(nodeptr, newChild) == 0) {
512 return IXML_HIERARCHY_REQUEST_ERR;
513 }
514 /* or if newChild is one of nodeptr's ancestors */
515 if (ixmlNode_isAncestor(newChild, nodeptr)) {
516 return IXML_HIERARCHY_REQUEST_ERR;
517 }
518 /* if newChild was created from a different document */
519 if (nodeptr->ownerDocument != newChild->ownerDocument) {
520 return IXML_WRONG_DOCUMENT_ERR;
521 }
522 /* if refChild is not a child of nodeptr */
523 if (ixmlNode_isParent(nodeptr, refChild) == 0) {
524 return IXML_NOT_FOUND_ERR;
525 }
526 if (refChild) {
527 if (ixmlNode_isParent(nodeptr, newChild)) {
528 ixmlNode_removeChild(nodeptr, newChild, &newChild);
529 newChild->nextSibling = NULL;
530 newChild->prevSibling = NULL;
531 }
532 newChild->nextSibling = refChild;
533 if (refChild->prevSibling) {
534 refChild->prevSibling->nextSibling = newChild;
535 newChild->prevSibling = refChild->prevSibling;
536 }
537 refChild->prevSibling = newChild;
538 if (!newChild->prevSibling) {
539 nodeptr->firstChild = newChild;
540 }
541 newChild->parentNode = nodeptr;
542 } else {
543 ret = ixmlNode_appendChild(nodeptr, newChild);
544 }
545
546 return ret;
547}
548
550 IXML_Node* oldChild, IXML_Node** returnNode) {
551 int ret = IXML_SUCCESS;
552
553 if (!nodeptr || !newChild || !oldChild) {
554 return IXML_INVALID_PARAMETER;
555 }
556 /* if nodetype of nodeptr does not allow children of the type of
557 * newChild needs to add later or if newChild is one of nodeptr's
558 * ancestors */
559 if (ixmlNode_isAncestor(newChild, nodeptr)) {
560 return IXML_HIERARCHY_REQUEST_ERR;
561 }
562 if (ixmlNode_allowChildren(nodeptr, newChild) == 0) {
563 return IXML_HIERARCHY_REQUEST_ERR;
564 }
565 /* if newChild was created from a different document */
566 if (nodeptr->ownerDocument != newChild->ownerDocument) {
567 return IXML_WRONG_DOCUMENT_ERR;
568 }
569 /* if refChild is not a child of nodeptr */
570 if (ixmlNode_isParent(nodeptr, oldChild) != 1) {
571 return IXML_NOT_FOUND_ERR;
572 }
573 ret = ixmlNode_insertBefore(nodeptr, newChild, oldChild);
574 if (ret != IXML_SUCCESS) {
575 return ret;
576 }
577 ret = ixmlNode_removeChild(nodeptr, oldChild, returnNode);
578 return ret;
579}
580
582 IXML_Node** returnNode) {
583 if (!nodeptr || !oldChild) {
584 return IXML_INVALID_PARAMETER;
585 }
586 if (!ixmlNode_isParent(nodeptr, oldChild)) {
587 return IXML_NOT_FOUND_ERR;
588 }
589 if (oldChild->prevSibling) {
590 oldChild->prevSibling->nextSibling = oldChild->nextSibling;
591 }
592 if (nodeptr->firstChild == oldChild) {
593 nodeptr->firstChild = oldChild->nextSibling;
594 }
595 if (oldChild->nextSibling) {
596 oldChild->nextSibling->prevSibling = oldChild->prevSibling;
597 }
598 oldChild->nextSibling = NULL;
599 oldChild->prevSibling = NULL;
600 oldChild->parentNode = NULL;
601 if (returnNode) {
602 *returnNode = oldChild;
603 } else {
604 ixmlNode_free(oldChild);
605 }
606
607 return IXML_SUCCESS;
608}
609
610int ixmlNode_appendChild(IXML_Node* nodeptr, IXML_Node* newChild) {
611 IXML_Node* prev = NULL;
612 IXML_Node* next = NULL;
613
614 if (!nodeptr || !newChild) {
615 return IXML_INVALID_PARAMETER;
616 }
617 /* if newChild was created from a different document */
618 if (newChild->ownerDocument &&
619 nodeptr->ownerDocument != newChild->ownerDocument) {
620 return IXML_WRONG_DOCUMENT_ERR;
621 }
622 /* if newChild is an ancestor of nodeptr */
623 if (ixmlNode_isAncestor(newChild, nodeptr)) {
624 return IXML_HIERARCHY_REQUEST_ERR;
625 }
626 /* if nodeptr does not allow to have newChild as children */
627 if (ixmlNode_allowChildren(nodeptr, newChild) == 0) {
628 return IXML_HIERARCHY_REQUEST_ERR;
629 }
630 if (ixmlNode_isParent(nodeptr, newChild)) {
631 ixmlNode_removeChild(nodeptr, newChild, &newChild);
632 }
633 /* set the parent node pointer */
634 newChild->parentNode = nodeptr;
635 newChild->ownerDocument = nodeptr->ownerDocument;
636 /* if the first child */
637 if (!nodeptr->firstChild) {
638 nodeptr->firstChild = newChild;
639 } else {
640 prev = nodeptr->firstChild;
641 next = prev->nextSibling;
642 while (next) {
643 prev = next;
644 next = prev->nextSibling;
645 }
646 prev->nextSibling = newChild;
647 newChild->prevSibling = prev;
648 }
649
650 return IXML_SUCCESS;
651}
652
660 IXML_Node* nodeptr) {
661 IXML_Node* newNode = NULL;
662 int rc;
663
664 assert(nodeptr);
665
666 newNode = (IXML_Node*)malloc(sizeof(IXML_Node));
667 if (!newNode) {
668 return NULL;
669 } else {
670 ixmlNode_init(newNode);
671 rc = ixmlNode_setNodeName(newNode, nodeptr->nodeName);
672 if (rc != IXML_SUCCESS) {
673 ixmlNode_free(newNode);
674 return NULL;
675 }
676 rc = ixmlNode_setNodeValue(newNode, nodeptr->nodeValue);
677 if (rc != IXML_SUCCESS) {
678 ixmlNode_free(newNode);
679 return NULL;
680 }
681 newNode->nodeType = eTEXT_NODE;
682 }
683
684 return newNode;
685}
686
694 IXML_CDATASection* nodeptr) {
695 IXML_CDATASection* newCDATA = NULL;
696 IXML_Node* newNode;
697 IXML_Node* srcNode;
698 int rc;
699
700 assert(nodeptr);
701 newCDATA = (IXML_CDATASection*)malloc(sizeof(IXML_CDATASection));
702 if (newCDATA) {
703 newNode = (IXML_Node*)newCDATA;
704 ixmlCDATASection_init(newCDATA);
705 srcNode = (IXML_Node*)nodeptr;
706 rc = ixmlNode_setNodeName(newNode, srcNode->nodeName);
707 if (rc != IXML_SUCCESS) {
708 ixmlCDATASection_free(newCDATA);
709 return NULL;
710 }
711 rc = ixmlNode_setNodeValue(newNode, srcNode->nodeValue);
712 if (rc != IXML_SUCCESS) {
713 ixmlCDATASection_free(newCDATA);
714 return NULL;
715 }
716 newNode->nodeType = eCDATA_SECTION_NODE;
717 }
718
719 return newCDATA;
720}
721
729 IXML_Element* nodeptr) {
730 IXML_Element* newElement;
731 IXML_Node* elementNode;
732 IXML_Node* srcNode;
733 int rc;
734
735 assert(nodeptr);
736
737 newElement = (IXML_Element*)malloc(sizeof(IXML_Element));
738 if (!newElement) {
739 return NULL;
740 }
741 ixmlElement_init(newElement);
742 rc = ixmlElement_setTagName(newElement, nodeptr->tagName);
743 if (rc != IXML_SUCCESS) {
744 ixmlElement_free(newElement);
745 return NULL;
746 }
747 elementNode = (IXML_Node*)newElement;
748 srcNode = (IXML_Node*)nodeptr;
749 rc = ixmlNode_setNodeName(elementNode, srcNode->nodeName);
750 if (rc != IXML_SUCCESS) {
751 ixmlElement_free(newElement);
752 return NULL;
753 }
754 rc = ixmlNode_setNodeValue(elementNode, srcNode->nodeValue);
755 if (rc != IXML_SUCCESS) {
756 ixmlElement_free(newElement);
757 return NULL;
758 }
759 rc = ixmlNode_setNamespaceURI(elementNode, srcNode->namespaceURI);
760 if (rc != IXML_SUCCESS) {
761 ixmlElement_free(newElement);
762 return NULL;
763 }
764 rc = ixmlNode_setPrefix(elementNode, srcNode->prefix);
765 if (rc != IXML_SUCCESS) {
766 ixmlElement_free(newElement);
767 return NULL;
768 }
769 rc = ixmlNode_setLocalName(elementNode, srcNode->localName);
770 if (rc != IXML_SUCCESS) {
771 ixmlElement_free(newElement);
772 return NULL;
773 }
774 elementNode->nodeType = eELEMENT_NODE;
775
776 return newElement;
777}
778
788 IXML_Document* newDoc;
789 IXML_Node* docNode;
790 int rc;
791
792 newDoc = (IXML_Document*)malloc(sizeof(IXML_Document));
793 if (!newDoc) {
794 return NULL;
795 }
796 ixmlDocument_init(newDoc);
797 docNode = (IXML_Node*)newDoc;
799 if (rc != IXML_SUCCESS) {
800 ixmlDocument_free(newDoc);
801 return NULL;
802 }
803 newDoc->n.nodeType = eDOCUMENT_NODE;
804
805 return newDoc;
806}
807
815 IXML_Attr* nodeptr) {
816 IXML_Attr* newAttr;
817 IXML_Node* attrNode;
818 IXML_Node* srcNode;
819 int rc;
820
821 assert(nodeptr);
822
823 newAttr = (IXML_Attr*)malloc(sizeof(IXML_Attr));
824 if (!newAttr) {
825 return NULL;
826 }
827 ixmlAttr_init(newAttr);
828 attrNode = (IXML_Node*)newAttr;
829 srcNode = (IXML_Node*)nodeptr;
830 rc = ixmlNode_setNodeName(attrNode, srcNode->nodeName);
831 if (rc != IXML_SUCCESS) {
832 ixmlAttr_free(newAttr);
833 return NULL;
834 }
835 rc = ixmlNode_setNodeValue(attrNode, srcNode->nodeValue);
836 if (rc != IXML_SUCCESS) {
837 ixmlAttr_free(newAttr);
838 return NULL;
839 }
840 /* Check to see whether we need to split prefix and localname for
841 * attribute */
842 rc = ixmlNode_setNamespaceURI(attrNode, srcNode->namespaceURI);
843 if (rc != IXML_SUCCESS) {
844 ixmlAttr_free(newAttr);
845 return NULL;
846 }
847 rc = ixmlNode_setPrefix(attrNode, srcNode->prefix);
848 if (rc != IXML_SUCCESS) {
849 ixmlAttr_free(newAttr);
850 return NULL;
851 }
852 rc = ixmlNode_setLocalName(attrNode, srcNode->localName);
853 if (rc != IXML_SUCCESS) {
854 ixmlAttr_free(newAttr);
855 return NULL;
856 }
857 attrNode->nodeType = eATTRIBUTE_NODE;
858
859 return newAttr;
860}
861
869 IXML_Attr* nodeptr) {
870 IXML_Attr* newAttr;
871
872 assert(nodeptr);
873
874 newAttr = ixmlNode_cloneAttr(nodeptr);
875 if (newAttr) {
876 newAttr->specified = 1;
877 }
878
879 return newAttr;
880}
881
887 IXML_Node* nodeptr) {
888 IXML_Node* parentNode = nodeptr->parentNode;
889 IXML_Node* nextptr = nodeptr->nextSibling;
890
891 while (nextptr) {
892 nextptr->parentNode = parentNode;
893 nextptr = nextptr->nextSibling;
894 }
895}
896
904 IXML_Node* nodeptr,
906 int deep) {
907 IXML_Node* newNode = NULL;
908 IXML_Element* newElement = NULL;
909 IXML_Attr* newAttr = NULL;
910 IXML_CDATASection* newCDATA = NULL;
911 IXML_Document* newDoc = NULL;
912 IXML_Node* nextSib = NULL;
913
914 if (nodeptr) {
915 switch (nodeptr->nodeType) {
916 case eELEMENT_NODE:
917 newElement = ixmlNode_cloneElement((IXML_Element*)nodeptr);
918 if (!newElement) {
919 return NULL;
920 }
921 newElement->n.firstAttr =
922 ixmlNode_cloneNodeTreeRecursive(nodeptr->firstAttr, deep);
923 if (deep) {
924 newElement->n.firstChild =
925 ixmlNode_cloneNodeTreeRecursive(nodeptr->firstChild, deep);
926 if (newElement->n.firstChild) {
927 newElement->n.firstChild->parentNode =
928 (IXML_Node*)newElement;
929 ixmlNode_setSiblingNodesParent(newElement->n.firstChild);
930 }
931 nextSib =
932 ixmlNode_cloneNodeTreeRecursive(nodeptr->nextSibling, deep);
933 newElement->n.nextSibling = nextSib;
934 if (nextSib) {
935 nextSib->prevSibling = (IXML_Node*)newElement;
936 }
937 }
938 newNode = (IXML_Node*)newElement;
939 break;
940 case eATTRIBUTE_NODE:
941 newAttr = ixmlNode_cloneAttr((IXML_Attr*)nodeptr);
942 if (!newAttr)
943 return NULL;
944 nextSib =
945 ixmlNode_cloneNodeTreeRecursive(nodeptr->nextSibling, deep);
946 newAttr->n.nextSibling = nextSib;
947 if (nextSib) {
948 nextSib->prevSibling = (IXML_Node*)newAttr;
949 }
950 newNode = (IXML_Node*)newAttr;
951 break;
952 case eTEXT_NODE:
953 newNode = ixmlNode_cloneTextNode(nodeptr);
954 break;
955 case eCDATA_SECTION_NODE:
956 newCDATA = ixmlNode_cloneCDATASect((IXML_CDATASection*)nodeptr);
957 newNode = (IXML_Node*)newCDATA;
958 break;
959 case eDOCUMENT_NODE:
960 newDoc = ixmlNode_newDoc();
961 if (!newDoc) {
962 return NULL;
963 }
964 newNode = (IXML_Node*)newDoc;
965 if (deep) {
966 newNode->firstChild =
967 ixmlNode_cloneNodeTreeRecursive(nodeptr->firstChild, deep);
968 if (newNode->firstChild) {
969 newNode->firstChild->parentNode = newNode;
970 }
971 }
972 break;
973 case eINVALID_NODE:
974 case eENTITY_REFERENCE_NODE:
975 case eENTITY_NODE:
976 case ePROCESSING_INSTRUCTION_NODE:
977 case eCOMMENT_NODE:
978 case eDOCUMENT_TYPE_NODE:
979 case eDOCUMENT_FRAGMENT_NODE:
980 case eNOTATION_NODE:
981 break;
982 }
983 }
984
985 return newNode;
986}
987
995 IXML_Node* nodeptr,
997 int deep) {
998 IXML_Node* newNode = NULL;
999 IXML_Element* newElement;
1000 IXML_Node* childNode;
1001
1002 assert(nodeptr);
1003
1004 switch (nodeptr->nodeType) {
1005 case eELEMENT_NODE:
1006 newElement = ixmlNode_cloneElement((IXML_Element*)nodeptr);
1007 if (!newElement) {
1008 return NULL;
1009 }
1010 newElement->n.firstAttr =
1011 ixmlNode_cloneNodeTreeRecursive(nodeptr->firstAttr, deep);
1012 if (deep) {
1013 newElement->n.firstChild =
1014 ixmlNode_cloneNodeTreeRecursive(nodeptr->firstChild, deep);
1015 childNode = newElement->n.firstChild;
1016 while (childNode) {
1017 childNode->parentNode = (IXML_Node*)newElement;
1018 childNode = childNode->nextSibling;
1019 }
1020 newElement->n.nextSibling = NULL;
1021 }
1022 newNode = (IXML_Node*)newElement;
1023 break;
1024 case eATTRIBUTE_NODE:
1025 case eTEXT_NODE:
1026 case eCDATA_SECTION_NODE:
1027 case eDOCUMENT_NODE:
1028 newNode = ixmlNode_cloneNodeTreeRecursive(nodeptr, deep);
1029 break;
1030 case eINVALID_NODE:
1031 case eENTITY_REFERENCE_NODE:
1032 case eENTITY_NODE:
1033 case ePROCESSING_INSTRUCTION_NODE:
1034 case eCOMMENT_NODE:
1035 case eDOCUMENT_TYPE_NODE:
1036 case eDOCUMENT_FRAGMENT_NODE:
1037 case eNOTATION_NODE:
1038#if 0
1039 /* create a new node here? */
1040 newNode = (IXML_Node *)malloc(sizeof(IXML_Node));
1041 if (!newNode ) {
1042 return NULL;
1043 }
1044#endif
1045 break;
1046 }
1047
1048 /* by spec, the duplicate node has no parent */
1049 if (newNode) {
1050 newNode->parentNode = NULL;
1051 }
1052
1053 return newNode;
1054}
1055
1057 IXML_Node* node = 0;
1058
1059 if (!nodeptr) {
1060 goto end_function;
1061 }
1062 switch (nodeptr->nodeType) {
1063 case eATTRIBUTE_NODE:
1064 node = (IXML_Node*)ixmlNode_cloneAttrDirect((IXML_Attr*)nodeptr);
1065 break;
1066 default:
1067 node = ixmlNode_cloneNodeTree(nodeptr, deep);
1068 break;
1069 }
1070
1071end_function:
1072 return node;
1073}
1074
1076 IXML_Node* tempNode;
1077 IXML_NodeList* newNodeList;
1078 int rc;
1079
1080 if (!nodeptr) {
1081 return NULL;
1082 }
1083 newNodeList = (IXML_NodeList*)malloc(sizeof(IXML_NodeList));
1084 if (!newNodeList) {
1085 return NULL;
1086 }
1087 ixmlNodeList_init(newNodeList);
1088 tempNode = nodeptr->firstChild;
1089 while (tempNode) {
1090 rc = ixmlNodeList_addToNodeList(&newNodeList, tempNode);
1091 if (rc != IXML_SUCCESS) {
1092 ixmlNodeList_free(newNodeList);
1093 return NULL;
1094 }
1095 tempNode = tempNode->nextSibling;
1096 }
1097
1098 return newNodeList;
1099}
1100
1102 IXML_NamedNodeMap* returnNamedNodeMap = NULL;
1103 IXML_Node* tempNode;
1104 int rc;
1105
1106 if (!nodeptr) {
1107 return NULL;
1108 }
1109 switch (nodeptr->nodeType) {
1110 case eELEMENT_NODE:
1111 returnNamedNodeMap =
1112 (IXML_NamedNodeMap*)malloc(sizeof(IXML_NamedNodeMap));
1113 if (!returnNamedNodeMap) {
1114 return NULL;
1115 }
1116 ixmlNamedNodeMap_init(returnNamedNodeMap);
1117 tempNode = nodeptr->firstAttr;
1118 while (tempNode) {
1119 rc = ixmlNamedNodeMap_addToNamedNodeMap(&returnNamedNodeMap,
1120 tempNode);
1121 if (rc != IXML_SUCCESS) {
1122 ixmlNamedNodeMap_free(returnNamedNodeMap);
1123 return NULL;
1124 }
1125 tempNode = tempNode->nextSibling;
1126 }
1127 return returnNamedNodeMap;
1128 default:
1129 /* if not an ELEMENT_NODE */
1130 return NULL;
1131 }
1132}
1133
1135 if (!nodeptr) {
1136 return 0;
1137 }
1138
1139 return nodeptr->firstChild != NULL;
1140}
1141
1143 if (nodeptr) {
1144 switch (nodeptr->nodeType) {
1145 case eELEMENT_NODE:
1146 if (nodeptr->firstAttr)
1147 return 1;
1148 break;
1149 default:
1150 break;
1151 }
1152 }
1153
1154 return 0;
1155}
1156
1163 IXML_Node* n,
1165 const char* tagname,
1167 IXML_NodeList** list) {
1168 const char* name;
1169
1170 if (n) {
1171 if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
1172 name = ixmlNode_getNodeName(n);
1173 if (strcmp(tagname, name) == 0 || strcmp(tagname, "*") == 0) {
1175 }
1176 }
1178 tagname, list);
1180 tagname, list);
1181 }
1182}
1183
1184void ixmlNode_getElementsByTagName(IXML_Node* n, const char* tagname,
1185 IXML_NodeList** list) {
1186 const char* name;
1187
1188 assert(n && tagname);
1189
1190 if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
1191 name = ixmlNode_getNodeName(n);
1192 if (strcmp(tagname, name) == 0 || strcmp(tagname, "*") == 0) {
1194 }
1195 }
1197 list);
1198}
1199
1205 IXML_Node* n,
1207 const char* namespaceURI,
1209 const char* localName,
1211 IXML_NodeList** list) {
1212 const DOMString nsURI;
1213 const DOMString name;
1214
1215 if (n) {
1216 if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
1217 name = ixmlNode_getLocalName(n);
1218 nsURI = ixmlNode_getNamespaceURI(n);
1219
1220 if (name && nsURI &&
1221 (strcmp(namespaceURI, nsURI) == 0 ||
1222 strcmp(namespaceURI, "*") == 0) &&
1223 (strcmp(name, localName) == 0 || strcmp(localName, "*") == 0)) {
1225 }
1226 }
1228 namespaceURI, localName, list);
1230 namespaceURI, localName, list);
1231 }
1232}
1233
1234void ixmlNode_getElementsByTagNameNS(IXML_Node* n, const char* namespaceURI,
1235 const char* localName,
1236 IXML_NodeList** list) {
1237 const DOMString nsURI;
1238 const DOMString name;
1239
1240 assert(n && namespaceURI && localName);
1241
1242 if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
1243 name = ixmlNode_getLocalName(n);
1244 nsURI = ixmlNode_getNamespaceURI(n);
1245 if (name && nsURI &&
1246 (strcmp(namespaceURI, nsURI) == 0 ||
1247 strcmp(namespaceURI, "*") == 0) &&
1248 (strcmp(name, localName) == 0 || strcmp(localName, "*") == 0)) {
1250 }
1251 }
1252
1254 namespaceURI, localName, list);
1255}
1256
1257int ixmlNode_setNodeName(IXML_Node* node, const DOMString qualifiedName) {
1258 int rc = IXML_SUCCESS;
1259
1260 assert(node);
1261
1262 if (node->nodeName) {
1263 free(node->nodeName);
1264 node->nodeName = NULL;
1265 }
1266 if (qualifiedName) {
1267 /* set the name part */
1268 node->nodeName = strdup(qualifiedName);
1269 if (!node->nodeName) {
1270 return IXML_INSUFFICIENT_MEMORY;
1271 }
1273 if (rc != IXML_SUCCESS) {
1274 free(node->nodeName);
1275 }
1276 }
1277
1278 return rc;
1279}
1280
1282 int rc;
1283
1284 assert(destNode && src);
1285 if (!destNode || !src) {
1286 return IXML_INVALID_PARAMETER;
1287 }
1288 rc = ixmlNode_setNodeValue(destNode, src->nodeValue);
1289 if (rc != IXML_SUCCESS) {
1290 goto ErrorHandler;
1291 }
1292 rc = ixmlNode_setLocalName(destNode, src->localName);
1293 if (rc != IXML_SUCCESS) {
1294 goto ErrorHandler;
1295 }
1296 rc = ixmlNode_setPrefix(destNode, src->prefix);
1297 if (rc != IXML_SUCCESS) {
1298 goto ErrorHandler;
1299 }
1300 /* set nodetype */
1301 destNode->nodeType = src->nodeType;
1302
1303 return IXML_SUCCESS;
1304
1305ErrorHandler:
1306 if (destNode->nodeName) {
1307 free(destNode->nodeName);
1308 destNode->nodeName = NULL;
1309 }
1310 if (destNode->nodeValue) {
1311 free(destNode->nodeValue);
1312 destNode->nodeValue = NULL;
1313 }
1314 if (destNode->localName) {
1315 free(destNode->localName);
1316 destNode->localName = NULL;
1317 }
1318
1319 return IXML_INSUFFICIENT_MEMORY;
1320}
1321
1322#ifdef IXML_HAVE_SCRIPTSUPPORT
1323void ixmlNode_setCTag(IXML_Node* nodeptr, void* ctag) {
1324 if (nodeptr) {
1325 nodeptr->ctag = ctag;
1326 }
1327}
1328
1329void* ixmlNode_getCTag(IXML_Node* nodeptr) {
1330 if (nodeptr) {
1331 return nodeptr->ctag;
1332 } else {
1333 return NULL;
1334 }
1335}
1336#endif
Data structure representing a CDATA section node.
Definition ixml.hpp:162
Data structure common to all types of nodes.
Definition ixml.hpp:132
Data structure representing an Attribute node.
Definition ixml.hpp:177
Data structure representing a list of nodes.
Definition ixml.hpp:193
Data structure representing a list of named nodes.
Definition ixml.hpp:201
Data structure representing an Element node.
Definition ixml.hpp:169
Data structure representing the DOM Document.
Definition ixml.hpp:155
IXML_Document * ixmlNode_getOwnerDocument(IXML_Node *nodeptr)
Retrieves the document object associated with this Node.
Definition node.cpp:379
unsigned short ixmlNode_getNodeType(IXML_Node *nodeptr)
Retrieves the type of a Node. Note that not all possible return values are actually implemented.
Definition node.cpp:322
int ixmlNode_appendChild(IXML_Node *nodeptr, IXML_Node *newChild)
Appends a child Node to the list of children of a Node.
Definition node.cpp:610
int ixmlNode_setNodeValue(IXML_Node *nodeptr, const char *newNodeValue)
Assigns a new value to a Node.
Definition node.cpp:302
int ixmlNode_replaceChild(IXML_Node *nodeptr, IXML_Node *newChild, IXML_Node *oldChild, IXML_Node **returnNode)
Replaces an existing child Node with a new child Node in the list of children of a Node.
Definition node.cpp:549
PUPNP_Api void ixmlAttr_free(IXML_Attr *attrNode)
Frees an Attr node.
Definition attr.cpp:46
void ixmlCDATASection_init(IXML_CDATASection *nodeptr)
Initializes a CDATASection node.
Definition node.cpp:53
int ixmlNode_removeChild(IXML_Node *nodeptr, IXML_Node *oldChild, IXML_Node **returnNode)
Removes a child from the list of children of a Node.
Definition node.cpp:581
#define DOMString
The type of DOM strings.
Definition ixml.hpp:47
void ixmlNode_free(IXML_Node *nodeptr)
Frees a Node and all Nodes in its subtree.
Definition node.cpp:124
void ixmlCDATASection_free(IXML_CDATASection *nodeptr)
Frees a CDATASection node.
Definition node.cpp:57
IXML_Node * ixmlNode_cloneNode(IXML_Node *nodeptr, int deep)
Clones a Node.
Definition node.cpp:1056
IXML_Node * ixmlNode_getNextSibling(IXML_Node *nodeptr)
Retrieves the sibling Node immediately following this Node.
Definition node.cpp:371
PUPNP_Api void ixmlElement_init(IXML_Element *element)
Initializes a IXML_Element node.
Definition element.cpp:46
const DOMString ixmlNode_getNodeValue(IXML_Node *nodeptr)
Returns the value of the Node as a string.
Definition node.cpp:294
const DOMString ixmlNode_getNodeName(IXML_Node *nodeptr)
Returns the name of the Node, depending on what type of Node it is, in a read-only string.
Definition node.cpp:182
IXML_Node * ixmlNode_getParentNode(IXML_Node *nodeptr)
Retrieves the parent Node for a Node.
Definition node.cpp:330
PUPNP_Api void ixmlDocument_init(IXML_Document *nodeptr)
Initializes a Document node.
Definition document.cpp:45
const DOMString ixmlNode_getLocalName(IXML_Node *nodeptr)
Retrieves the local name of a Node, if present.
Definition node.cpp:190
IXML_NodeList * ixmlNode_getChildNodes(IXML_Node *nodeptr)
Retrieves the list of children of a Node in a NodeList structure.
Definition node.cpp:1075
int ixmlNode_insertBefore(IXML_Node *nodeptr, IXML_Node *newChild, IXML_Node *refChild)
Inserts a new child Node before the existing child Node.
Definition node.cpp:503
IXML_Node * ixmlNode_getLastChild(IXML_Node *nodeptr)
Retrieves the last child Node of a Node.
Definition node.cpp:346
const DOMString ixmlNode_getPrefix(IXML_Node *nodeptr)
Retrieves the namespace prefix, if present.
Definition node.cpp:284
PUPNP_Api void ixmlNodeList_free(IXML_NodeList *nList)
Frees a NodeList object.
Definition nodeList.cpp:129
int ixmlNode_hasAttributes(IXML_Node *nodeptr)
Queries whether this Node has attributes.
Definition node.cpp:1142
IXML_Node * ixmlNode_getPreviousSibling(IXML_Node *nodeptr)
Retrieves the sibling Node immediately preceding this Node.
Definition node.cpp:363
PUPNP_Api void ixmlElement_free(IXML_Element *element)
Frees the given Element and any subtree of the Element.
Definition element.cpp:646
#define DOCUMENTNODENAME
The type of the DOM node.
Definition ixml.hpp:114
const DOMString ixmlNode_getNamespaceURI(IXML_Node *nodeptr)
Retrieves the namespace URI for a Node as a DOMString.
Definition node.cpp:274
IXML_Node * ixmlNode_getFirstChild(IXML_Node *nodeptr)
Retrieves the first child Node of a Node.
Definition node.cpp:338
IXML_NamedNodeMap * ixmlNode_getAttributes(IXML_Node *nodeptr)
Retrieves the attributes of a Node, if it is an Element node, in a NamedNodeMap structure.
Definition node.cpp:1101
PUPNP_Api void ixmlNamedNodeMap_free(IXML_NamedNodeMap *nnMap)
Frees a NamedNodeMap.
int ixmlNode_hasChildNodes(IXML_Node *nodeptr)
Queries whether or not a Node has children.
Definition node.cpp:1134
PUPNP_Api void ixmlDocument_free(IXML_Document *doc)
Frees a Document object and all Nodes associated with it.
Definition document.cpp:49
int ixmlNodeList_addToNodeList(IXML_NodeList **nList, IXML_Node *add)
Add a node to nodelist.
Definition nodeList.cpp:74
void ixmlNamedNodeMap_init(IXML_NamedNodeMap *nnMap)
Initializes a NamedNodeMap object.
void ixmlNodeList_init(IXML_NodeList *nList)
Initializes a nodelist.
Definition nodeList.cpp:43
int ixmlElement_setTagName(IXML_Element *element, const char *tagName)
Set the given element's tagName.
Definition element.cpp:60
void ixmlAttr_init(IXML_Attr *attrNode)
ixmlAttr_init
Definition attr.cpp:40
int Parser_setNodePrefixAndLocalName(IXML_Node *newIXML_NodeIXML_Attr)
Set the node prefix and localName as defined by the nodeName in the form of ns:name.
int ixmlNamedNodeMap_addToNamedNodeMap(IXML_NamedNodeMap **nnMap, IXML_Node *add)
Add a node to a NamedNodeMap.
static void ixmlNode_setSiblingNodesParent(IXML_Node *nodeptr)
Sets siblings nodes parent to be the same as this node's.
Definition node.cpp:885
static int ixmlNode_setPrefix(IXML_Node *nodeptr, const char *prefix)
Set the prefix of the node.
Definition node.cpp:226
static int ixmlNode_allowChildren(IXML_Node *nodeptr, IXML_Node *newChild)
Check to see whether nodeptr allows children of type newChild.
Definition node.cpp:441
static IXML_CDATASection * ixmlNode_cloneCDATASect(IXML_CDATASection *nodeptr)
Return a clone of CDATASection node.
Definition node.cpp:692
int ixmlNode_setNodeProperties(IXML_Node *destNode, IXML_Node *src)
Definition node.cpp:1281
static IXML_Node * ixmlNode_cloneTextNode(IXML_Node *nodeptr)
Returns a clone of nodeptr.
Definition node.cpp:658
static void ixmlNode_freeSingleNode(IXML_Node *nodeptr)
Frees a node content.
Definition node.cpp:66
static int ixmlNode_isAncestor(IXML_Node *ancestorNode, IXML_Node *toFind)
Check if ancestorNode is ancestor of toFind.
Definition node.cpp:392
static IXML_Node * ixmlNode_cloneNodeTree(IXML_Node *nodeptr, int deep)
Function that clones a node tree of nodeptr.
Definition node.cpp:993
static int ixmlNode_setNamespaceURI(IXML_Node *nodeptr, const char *namespaceURI)
Sets the namespace URI of the node.
Definition node.cpp:201
static IXML_Attr * ixmlNode_cloneAttrDirect(IXML_Attr *nodeptr)
Return a clone of attribute node, with specified field set to 1.
Definition node.cpp:867
static IXML_Document * ixmlNode_newDoc(void)
Returns a new document node.
Definition node.cpp:787
static void ixmlNode_getElementsByTagNameNSRecursive(IXML_Node *n, const char *namespaceURI, const char *localName, IXML_NodeList **list)
ixmlNode_getElementsByTagNameNSRecursive
Definition node.cpp:1203
void ixmlNode_getElementsByTagName(IXML_Node *n, const char *tagname, IXML_NodeList **list)
Returns a nodeList of all descendant Elements with a given tagName, in the order in which they are en...
Definition node.cpp:1184
static IXML_Node * ixmlNode_cloneNodeTreeRecursive(IXML_Node *nodeptr, int deep)
Recursive function that clones a node tree of nodeptr.
Definition node.cpp:902
static void ixmlNode_getElementsByTagNameRecursive(IXML_Node *n, const char *tagname, IXML_NodeList **list)
Recursively traverse the whole tree, search for element with the given tagname.
Definition node.cpp:1161
void ixmlNode_init(IXML_Node *nodeptr)
Intializes a node.
Definition node.cpp:47
int ixmlNode_setNodeName(IXML_Node *node, const DOMString qualifiedName)
Definition node.cpp:1257
static int ixmlNode_isParent(IXML_Node *nodeptr, IXML_Node *toFind)
Check whether toFind is a children of nodeptr.
Definition node.cpp:418
static IXML_Element * ixmlNode_cloneElement(IXML_Element *nodeptr)
Returns a clone of element node.
Definition node.cpp:727
static IXML_Attr * ixmlNode_cloneAttr(IXML_Attr *nodeptr)
Returns a clone of an attribute node.
Definition node.cpp:813
static int ixmlNode_setLocalName(IXML_Node *nodeptr, const char *localName)
Set the localName of the node.
Definition node.cpp:253
int ixmlNode_compare(const IXML_Node *srcNode, const IXML_Node *destNode)
Compare two nodes to see whether they are the same node. Parent, sibling and children node are ignore...
Definition node.cpp:485
void ixmlNode_getElementsByTagNameNS(IXML_Node *n, const char *namespaceURI, const char *localName, IXML_NodeList **list)
Returns a nodeList of all the descendant Elements with a given local name and namespace URI in the or...
Definition node.cpp:1234