1///////////////////////////////////////////////////////////////////////////
2//
3// Copyright (c) 2000-2003 Intel Corporation
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are met:
8//
9// * Redistributions of source code must retain the above copyright notice,
10// this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above copyright notice,
12// this list of conditions and the following disclaimer in the documentation
13// and/or other materials provided with the distribution.
14// * Neither name of Intel Corporation nor the names of its contributors
15// may be used to endorse or promote products derived from this software
16// without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
22// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29//
30///////////////////////////////////////////////////////////////////////////
31
32#include "ixmlparser.h"
33
34/*================================================================
35*   ixmlNode_init
36*       Intializes a node.
37*       External function.
38*
39*=================================================================*/
40void
41ixmlNode_init( IN IXML_Node * nodeptr )
42{
43    assert( nodeptr != NULL );
44    memset( nodeptr, 0, sizeof( IXML_Node ) );
45
46}
47
48/*================================================================
49*   ixmlCDATASection_init
50*       Initializes a CDATASection node.
51*       External function.
52*
53*=================================================================*/
54void
55ixmlCDATASection_init( IN IXML_CDATASection * nodeptr )
56{
57    memset( nodeptr, 0, sizeof( IXML_CDATASection ) );
58}
59
60/*================================================================
61*   ixmlCDATASection_free
62*       frees a CDATASection node.
63*       External function.
64*
65*=================================================================*/
66void
67ixmlCDATASection_free( IN IXML_CDATASection * nodeptr )
68{
69    if( nodeptr != NULL ) {
70        ixmlNode_free( ( IXML_Node * ) nodeptr );
71    }
72}
73
74/*================================================================
75*   ixmlNode_freeSingleNode
76*       frees a node content.
77*       Internal to parser only.
78*
79*=================================================================*/
80void
81ixmlNode_freeSingleNode( IN IXML_Node * nodeptr )
82{
83    IXML_Element *element = NULL;
84
85    if( nodeptr != NULL ) {
86        if( nodeptr->nodeName != NULL ) {
87            free( nodeptr->nodeName );
88        }
89
90        if( nodeptr->nodeValue != NULL ) {
91            free( nodeptr->nodeValue );
92        }
93
94        if( nodeptr->namespaceURI != NULL ) {
95            free( nodeptr->namespaceURI );
96        }
97
98        if( nodeptr->prefix != NULL ) {
99            free( nodeptr->prefix );
100        }
101
102        if( nodeptr->localName != NULL ) {
103            free( nodeptr->localName );
104        }
105
106        if( nodeptr->nodeType == eELEMENT_NODE ) {
107            element = ( IXML_Element * ) nodeptr;
108            free( element->tagName );
109        }
110
111        free( nodeptr );
112
113    }
114}
115
116/*================================================================
117*   ixmlNode_free
118*       Frees all nodes under nodeptr subtree.
119*       External function.
120*
121*=================================================================*/
122void
123ixmlNode_free( IN IXML_Node * nodeptr )
124{
125    if( nodeptr != NULL ) {
126        ixmlNode_free( nodeptr->firstChild );
127        ixmlNode_free( nodeptr->nextSibling );
128        ixmlNode_free( nodeptr->firstAttr );
129
130        ixmlNode_freeSingleNode( nodeptr );
131    }
132}
133
134/*================================================================
135*   ixmlNode_getNodeName
136*       Returns the nodename(the qualified name)
137*       External function.
138*
139*=================================================================*/
140const DOMString
141ixmlNode_getNodeName( IN IXML_Node * nodeptr )
142{
143
144    if( nodeptr != NULL ) {
145        return ( nodeptr->nodeName );
146    }
147
148    return NULL;
149}
150
151/*================================================================
152*   ixmlNode_getLocalName
153*       Returns the node local name
154*       External function.
155*
156*=================================================================*/
157const DOMString
158ixmlNode_getLocalName( IN IXML_Node * nodeptr )
159{
160
161    if( nodeptr != NULL ) {
162        return ( nodeptr->localName );
163    }
164
165    return NULL;
166}
167
168/*================================================================
169*   ixmlNode_setNamespaceURI
170*       sets the namespace URI of the node.
171*       Internal function.
172*	Return:
173*       IXML_SUCCESS or failure
174*
175*=================================================================*/
176int
177ixmlNode_setNamespaceURI( IN IXML_Node * nodeptr,
178                          IN char *namespaceURI )
179{
180
181    if( nodeptr == NULL ) {
182        return IXML_INVALID_PARAMETER;
183    }
184
185    if( nodeptr->namespaceURI != NULL ) {
186        free( nodeptr->namespaceURI );
187        nodeptr->namespaceURI = NULL;
188    }
189
190    if( namespaceURI != NULL ) {
191        nodeptr->namespaceURI = strdup( namespaceURI );
192        if( nodeptr->namespaceURI == NULL ) {
193            return IXML_INSUFFICIENT_MEMORY;
194        }
195    }
196
197    return IXML_SUCCESS;
198}
199
200/*================================================================
201*   ixmlNode_setPrefix
202*       set the prefix of the node.
203*       Internal to parser only.
204*	Returns:
205*       IXML_SUCCESS or failure.
206*
207*=================================================================*/
208int
209ixmlNode_setPrefix( IN IXML_Node * nodeptr,
210                    IN char *prefix )
211{
212
213    if( nodeptr == NULL ) {
214        return IXML_INVALID_PARAMETER;
215    }
216
217    if( nodeptr->prefix != NULL ) {
218        free( nodeptr->prefix );
219        nodeptr->prefix = NULL;
220    }
221
222    if( prefix != NULL ) {
223        nodeptr->prefix = strdup( prefix );
224        if( nodeptr->prefix == NULL ) {
225            return IXML_INSUFFICIENT_MEMORY;
226        }
227    }
228
229    return IXML_SUCCESS;
230
231}
232
233/*================================================================
234*   ixmlNode_setLocalName
235*	    set the localName of the node.
236*       Internal to parser only.
237*	Returns:
238*       IXML_SUCCESS or failure.
239*
240*=================================================================*/
241int
242ixmlNode_setLocalName( IN IXML_Node * nodeptr,
243                       IN char *localName )
244{
245
246    assert( nodeptr != NULL );
247
248    if( nodeptr->localName != NULL ) {
249        free( nodeptr->localName );
250        nodeptr->localName = NULL;
251    }
252
253    if( localName != NULL ) {
254        nodeptr->localName = strdup( localName );
255        if( nodeptr->localName == NULL ) {
256            return IXML_INSUFFICIENT_MEMORY;
257        }
258    }
259
260    return IXML_SUCCESS;
261}
262
263/*================================================================
264*   ixmlNode_getNodeNamespaceURI
265*       Returns the node namespaceURI
266*       External function.
267*   Returns:
268*       the namespaceURI of the node
269*
270*=================================================================*/
271const DOMString
272ixmlNode_getNamespaceURI( IN IXML_Node * nodeptr )
273{
274    DOMString retNamespaceURI = NULL;
275
276    if( nodeptr != NULL ) {
277        retNamespaceURI = nodeptr->namespaceURI;
278    }
279
280    return retNamespaceURI;
281}
282
283/*================================================================
284*   ixmlNode_getPrefix
285*       Returns the node prefix
286*       External function.
287*   Returns:
288*       the prefix of the node.
289*
290*=================================================================*/
291DOMString
292ixmlNode_getPrefix( IN IXML_Node * nodeptr )
293{
294    DOMString prefix = NULL;
295
296    if( nodeptr != NULL ) {
297        prefix = nodeptr->prefix;
298    }
299
300    return prefix;
301
302}
303
304/*================================================================
305*   ixmlNode_getNodeValue
306*       Returns the nodeValue of this node
307*       External function.
308*   Return:
309*       the nodeValue of the node.
310*
311*=================================================================*/
312DOMString
313ixmlNode_getNodeValue( IN IXML_Node * nodeptr )
314{
315
316    if( nodeptr != NULL ) {
317        return ( nodeptr->nodeValue );
318    }
319
320    return NULL;
321}
322
323/*================================================================
324*   ixmlNode_setNodeValue
325*       Sets the nodeValue
326*       Internal function.
327*   Returns:
328*       IXML_SUCCESS or failure
329*
330*=================================================================*/
331int
332ixmlNode_setNodeValue( IN IXML_Node * nodeptr,
333                       IN char *newNodeValue )
334{
335    int rc = IXML_SUCCESS;
336
337    if( nodeptr == NULL ) {
338        return IXML_INVALID_PARAMETER;
339    }
340
341    if( nodeptr->nodeValue != NULL ) {
342        free( nodeptr->nodeValue );
343        nodeptr->nodeValue = NULL;
344    }
345
346    if( newNodeValue != NULL ) {
347        nodeptr->nodeValue = strdup( newNodeValue );
348        if( nodeptr->nodeValue == NULL ) {
349            return IXML_INSUFFICIENT_MEMORY;
350        }
351    }
352
353    return rc;
354}
355
356/*================================================================
357*   ixmlNode_getNodeType
358*       Gets the NodeType of this node
359*       External function.
360*
361*=================================================================*/
362const unsigned short
363ixmlNode_getNodeType( IN IXML_Node * nodeptr )
364{
365    if( nodeptr != NULL ) {
366        return ( nodeptr->nodeType );
367    } else {
368        return ( eINVALID_NODE );
369    }
370}
371
372/*================================================================
373*   ixmlNode_getParentNode
374*       Get the parent node
375*       External function.
376*   Return:
377*
378*=================================================================*/
379IXML_Node *
380ixmlNode_getParentNode( IN IXML_Node * nodeptr )
381{
382
383    if( nodeptr != NULL ) {
384        return nodeptr->parentNode;
385    } else {
386        return NULL;
387    }
388}
389
390/*================================================================
391*   ixmlNode_getFirstChild
392*       Returns the first child of nodeptr.
393*       External function.
394*
395*=================================================================*/
396IXML_Node *
397ixmlNode_getFirstChild( IN IXML_Node * nodeptr )
398{
399    if( nodeptr != NULL ) {
400        return nodeptr->firstChild;
401    } else {
402        return NULL;
403    }
404}
405
406/*================================================================
407*   ixmlNode_getLastChild
408*       Returns the last child of nodeptr.
409*       External function.
410*
411*=================================================================*/
412IXML_Node *
413ixmlNode_getLastChild( IN IXML_Node * nodeptr )
414{
415    IXML_Node *prev,
416     *next;
417
418    if( nodeptr != NULL ) {
419        prev = nodeptr;
420        next = nodeptr->firstChild;
421
422        while( next != NULL ) {
423            prev = next;
424            next = next->nextSibling;
425        }
426        return prev;
427    } else {
428        return NULL;
429    }
430
431}
432
433/*================================================================
434*   ixmlNode_getPreviousSibling
435*       returns the previous sibling node of nodeptr.
436*       External function.
437*
438*=================================================================*/
439IXML_Node *
440ixmlNode_getPreviousSibling( IN IXML_Node * nodeptr )
441{
442    if( nodeptr != NULL ) {
443        return nodeptr->prevSibling;
444    } else {
445        return NULL;
446    }
447}
448
449/*================================================================
450*   ixmlNode_getNextSibling
451*       Returns the next sibling node.
452*       External function.
453*
454*=================================================================*/
455IXML_Node *
456ixmlNode_getNextSibling( IN IXML_Node * nodeptr )
457{
458
459    if( nodeptr != NULL ) {
460        return nodeptr->nextSibling;
461    } else {
462        return NULL;
463    }
464
465}
466
467/*================================================================
468*   ixmlNode_getOwnerDocument
469*       Returns the owner document node.
470*       External function.
471*
472*=================================================================*/
473IXML_Document *
474ixmlNode_getOwnerDocument( IN IXML_Node * nodeptr )
475{
476    if( nodeptr != NULL ) {
477        return ( IXML_Document * ) nodeptr->ownerDocument;
478    } else {
479        return NULL;
480    }
481}
482
483/*================================================================
484*   ixmlNode_isAncestor
485*       check if ancestorNode is ancestor of toFind
486*       Internal to parser only.
487*   Returns:
488*       TRUE or FALSE
489*
490*=================================================================*/
491BOOL
492ixmlNode_isAncestor( IXML_Node * ancestorNode,
493                     IXML_Node * toFind )
494{
495
496    BOOL found = FALSE;
497
498    if( ( ancestorNode != NULL ) && ( toFind != NULL ) ) {
499        if( toFind->parentNode == ancestorNode ) {
500            return TRUE;
501        } else {
502            found =
503                ixmlNode_isAncestor( ancestorNode->firstChild, toFind );
504            if( found == FALSE ) {
505                found =
506                    ixmlNode_isAncestor( ancestorNode->nextSibling,
507                                         toFind );
508            }
509        }
510    }
511
512    return found;
513}
514
515/*================================================================
516*   ixmlNode_isParent
517*       Check whether toFind is a children of nodeptr.
518*       Internal to parser only.
519*   Return:
520*       TRUE or FALSE
521*
522*=================================================================*/
523BOOL
524ixmlNode_isParent( IXML_Node * nodeptr,
525                   IXML_Node * toFind )
526{
527    BOOL found = FALSE;
528
529    assert( nodeptr != NULL && toFind != NULL );
530    if( toFind->parentNode == nodeptr ) {
531        found = TRUE;
532    }
533
534    return found;
535}
536
537/*================================================================
538*   ixmlNode_allowChildren
539*       Check to see whether nodeptr allows children of type newChild.
540*       Internal to parser only.
541*   Returns:
542*       TRUE, if nodeptr can have newChild as children
543*       FALSE,if nodeptr cannot have newChild as children
544*
545*=================================================================*/
546BOOL
547ixmlNode_allowChildren( IXML_Node * nodeptr,
548                        IXML_Node * newChild )
549{
550
551    assert( nodeptr != NULL && newChild != NULL );
552    switch ( nodeptr->nodeType ) {
553        case eATTRIBUTE_NODE:
554        case eTEXT_NODE:
555        case eCDATA_SECTION_NODE:
556            return FALSE;
557            break;
558
559        case eELEMENT_NODE:
560            if( ( newChild->nodeType == eATTRIBUTE_NODE ) ||
561                ( newChild->nodeType == eDOCUMENT_NODE ) ) {
562                return FALSE;
563            }
564            break;
565
566        case eDOCUMENT_NODE:
567            if( newChild->nodeType != eELEMENT_NODE ) {
568                return FALSE;
569            }
570
571        default:
572            break;
573    }
574
575    return TRUE;
576}
577
578/*================================================================
579*   ixmlNode_compare
580*       Compare two nodes to see whether they are the same node.
581*       Parent, sibling and children node are ignored.
582*       Internal to parser only.
583*   Returns:
584*       TRUE, the two nodes are the same.
585*       FALSE, the two nodes are not the same.
586*
587*=================================================================*/
588BOOL
589ixmlNode_compare( IXML_Node * srcNode,
590                  IXML_Node * destNode )
591{
592    assert( srcNode != NULL && destNode != NULL );
593    if( ( srcNode == destNode ) ||
594        ( strcmp( srcNode->nodeName, destNode->nodeName ) == 0 &&
595          strcmp( srcNode->nodeValue, destNode->nodeValue ) == 0 &&
596          ( srcNode->nodeType == destNode->nodeType ) &&
597          strcmp( srcNode->namespaceURI, destNode->namespaceURI ) == 0 &&
598          strcmp( srcNode->prefix, destNode->prefix ) == 0 &&
599          strcmp( srcNode->localName, destNode->localName ) == 0 ) ) {
600        return TRUE;
601    } else {
602        return FALSE;
603    }
604}
605
606/*================================================================
607*   ixmlNode_insertBefore
608*       Inserts the node newChild before the existing child node refChild.
609*       If refChild is null, insert newChild at the end of the list of
610*       children. If the newChild is already in the tree, it is first
611*       removed.
612*       External function.
613*   Parameters:
614*       newChild: the node to insert.
615*   Returns:
616*
617*=================================================================*/
618int
619ixmlNode_insertBefore( IN IXML_Node * nodeptr,
620                       IN IXML_Node * newChild,
621                       IN IXML_Node * refChild )
622{
623
624    int ret = IXML_SUCCESS;
625
626    if( ( nodeptr == NULL ) || ( newChild == NULL ) ) {
627        return IXML_INVALID_PARAMETER;
628    }
629    // whether nodeptr allow children of the type of newChild
630    if( ixmlNode_allowChildren( nodeptr, newChild ) == FALSE ) {
631        return IXML_HIERARCHY_REQUEST_ERR;
632    }
633    // or if newChild is one of nodeptr's ancestors
634    if( ixmlNode_isAncestor( newChild, nodeptr ) == TRUE ) {
635        return IXML_HIERARCHY_REQUEST_ERR;
636    }
637    // if newChild was created from a different document
638    if( nodeptr->ownerDocument != newChild->ownerDocument ) {
639        return IXML_WRONG_DOCUMENT_ERR;
640    }
641    // if refChild is not a child of nodeptr
642    if( ixmlNode_isParent( nodeptr, refChild ) == FALSE ) {
643        return IXML_NOT_FOUND_ERR;
644    }
645
646    if( refChild != NULL ) {
647        if( ixmlNode_isParent( nodeptr, newChild ) == TRUE ) {
648            ixmlNode_removeChild( nodeptr, newChild, NULL );
649            newChild->nextSibling = NULL;
650            newChild->prevSibling = NULL;
651        }
652
653        newChild->nextSibling = refChild;
654        if( refChild->prevSibling != NULL ) {
655            ( refChild->prevSibling )->nextSibling = newChild;
656            newChild->prevSibling = refChild->prevSibling;
657        }
658
659        refChild->prevSibling = newChild;
660
661        if( newChild->prevSibling == NULL ) {
662            nodeptr->firstChild = newChild;
663        }
664
665        newChild->parentNode = nodeptr;
666
667    } else {
668        ret = ixmlNode_appendChild( nodeptr, newChild );
669    }
670
671    return ret;
672}
673
674/*================================================================
675*   ixmlNode_replaceChild
676*       Replaces the child node oldChild with newChild in the list of children,
677*       and returns the oldChild node.
678*       External function.
679*   Parameters:
680*       newChild:   the new node to put in the child list.
681*       oldChild:   the node being replaced in the list.
682*       returnNode: the node replaced.
683*   Return Value:
684*       IXML_SUCCESS
685*       IXML_INVALID_PARAMETER:     if anyone of nodeptr, newChild or oldChild is NULL.
686*       IXML_HIERARCHY_REQUEST_ERR: if the newChild is ancestor of nodeptr or nodeptr
687*                                   is of a type that does not allow children of the
688*                                   type of the newChild node.
689*       IXML_WRONG_DOCUMENT_ERR:    if newChild was created from a different document than
690*                                   the one that created this node.
691*       IXML_NOT_FOUND_ERR:         if oldChild is not a child of nodeptr.
692*
693*=================================================================*/
694int
695ixmlNode_replaceChild( IN IXML_Node * nodeptr,
696                       IN IXML_Node * newChild,
697                       IN IXML_Node * oldChild,
698                       OUT IXML_Node ** returnNode )
699{
700    int ret = IXML_SUCCESS;
701
702    if( ( nodeptr == NULL ) || ( newChild == NULL )
703        || ( oldChild == NULL ) ) {
704        return IXML_INVALID_PARAMETER;
705    }
706    // if nodetype of nodeptr does not allow children of the type of newChild
707    // needs to add later
708
709    // or if newChild is one of nodeptr's ancestors
710    if( ixmlNode_isAncestor( newChild, nodeptr ) == TRUE ) {
711        return IXML_HIERARCHY_REQUEST_ERR;
712    }
713
714    if( ixmlNode_allowChildren( nodeptr, newChild ) == FALSE ) {
715        return IXML_HIERARCHY_REQUEST_ERR;
716    }
717    // if newChild was created from a different document
718    if( nodeptr->ownerDocument != newChild->ownerDocument ) {
719        return IXML_WRONG_DOCUMENT_ERR;
720    }
721    // if refChild is not a child of nodeptr
722    if( ixmlNode_isParent( nodeptr, oldChild ) != TRUE ) {
723        return IXML_NOT_FOUND_ERR;
724    }
725
726    ret = ixmlNode_insertBefore( nodeptr, newChild, oldChild );
727    if( ret != IXML_SUCCESS ) {
728        return ret;
729    }
730
731    ret = ixmlNode_removeChild( nodeptr, oldChild, returnNode );
732    return ret;
733}
734
735/*================================================================
736*   ixmlNode_removeChild
737*       Removes the child node indicated by oldChild from the list of
738*       children, and returns it.
739*       External function.
740*   Parameters:
741*       oldChild: the node being removed.
742*       returnNode: the node removed.
743*   Return Value:
744*       IXML_SUCCESS
745*       IXML_NOT_FOUND_ERR: if oldChild is not a child of this node.
746*       IXML_INVALID_PARAMETER: if either oldChild or nodeptr is NULL
747*
748*=================================================================*/
749int
750ixmlNode_removeChild( IN IXML_Node * nodeptr,
751                      IN IXML_Node * oldChild,
752                      OUT IXML_Node ** returnNode )
753{
754
755    if( ( nodeptr == NULL ) || ( oldChild == NULL ) ) {
756        return IXML_INVALID_PARAMETER;
757    }
758
759    if( ixmlNode_isParent( nodeptr, oldChild ) == FALSE ) {
760        return IXML_NOT_FOUND_ERR;
761    }
762
763    if( oldChild->prevSibling != NULL ) {
764        ( oldChild->prevSibling )->nextSibling = oldChild->nextSibling;
765    }
766
767    if( nodeptr->firstChild == oldChild ) {
768        nodeptr->firstChild = oldChild->nextSibling;
769    }
770
771    if( oldChild->nextSibling != NULL ) {
772        ( oldChild->nextSibling )->prevSibling = oldChild->prevSibling;
773    }
774
775    oldChild->nextSibling = NULL;
776    oldChild->prevSibling = NULL;
777    oldChild->parentNode = NULL;
778
779    if( returnNode != NULL ) {
780        *returnNode = oldChild;
781    }
782    return IXML_SUCCESS;
783}
784
785/*=============================================================================
786*   ixmlNode_appendChild
787*       Adds the node newChild to the end of the list of children of this node.
788*       If the newChild is already in the tree, it is first removed.
789*       External function.
790*   Parameter:
791*       newChild: the node to add.
792*   Return Value:
793*       IXML_SUCCESS
794*       IXML_INVALID_PARAMETER:     if either nodeptr or newChild is NULL
795*       IXML_WRONG_DOCUMENT_ERR:    if newChild was created from a different document than
796*                                   the one that created nodeptr.
797*       IXML_HIERARCHY_REQUEST_ERR: if newChild is ancestor of nodeptr or if nodeptr is of
798*                                   a type that does not allow children of the type of the
799*                                   newChild node.
800*
801*=================================================================*/
802int
803ixmlNode_appendChild( IN IXML_Node * nodeptr,
804                      IN IXML_Node * newChild )
805{
806
807    IXML_Node *prev = NULL,
808     *next = NULL;
809
810    if( ( nodeptr == NULL ) || ( newChild == NULL ) ) {
811        return IXML_INVALID_PARAMETER;
812    }
813    // if newChild was created from a different document
814    if( ( newChild->ownerDocument != NULL ) &&
815        ( nodeptr->ownerDocument != newChild->ownerDocument ) ) {
816        return IXML_WRONG_DOCUMENT_ERR;
817    }
818    // if newChild is an ancestor of nodeptr
819    if( ixmlNode_isAncestor( newChild, nodeptr ) == TRUE ) {
820        return IXML_HIERARCHY_REQUEST_ERR;
821    }
822    // if nodeptr does not allow to have newChild as children
823    if( ixmlNode_allowChildren( nodeptr, newChild ) == FALSE ) {
824        return IXML_HIERARCHY_REQUEST_ERR;
825    }
826
827    if( ixmlNode_isParent( nodeptr, newChild ) == TRUE ) {
828        ixmlNode_removeChild( nodeptr, newChild, NULL );
829    }
830    // set the parent node pointer
831    newChild->parentNode = nodeptr;
832    newChild->ownerDocument = nodeptr->ownerDocument;
833
834    //if the first child
835    if( nodeptr->firstChild == NULL ) {
836        nodeptr->firstChild = newChild;
837    } else {
838        prev = nodeptr->firstChild;
839        next = prev->nextSibling;
840        while( next != NULL ) {
841            prev = next;
842            next = prev->nextSibling;
843        }
844        prev->nextSibling = newChild;
845        newChild->prevSibling = prev;
846    }
847
848    return IXML_SUCCESS;
849}
850
851/*================================================================
852*   ixmlNode_cloneTextNode
853*       Returns a clone of nodeptr
854*       Internal to parser only.
855*
856*=================================================================*/
857IXML_Node *
858ixmlNode_cloneTextNode( IN IXML_Node * nodeptr )
859{
860    IXML_Node *newNode = NULL;
861
862    assert( nodeptr != NULL );
863
864    newNode = ( IXML_Node * ) malloc( sizeof( IXML_Node ) );
865    if( newNode == NULL ) {
866        return NULL;
867    } else {
868        ixmlNode_init( newNode );
869
870        ixmlNode_setNodeName( newNode, nodeptr->nodeName );
871        ixmlNode_setNodeValue( newNode, nodeptr->nodeValue );
872        newNode->nodeType = eTEXT_NODE;
873    }
874
875    return newNode;
876}
877
878/*================================================================
879*   ixmlNode_cloneCDATASect
880*       Return a clone of CDATASection node.
881*       Internal to parser only.
882*
883*=================================================================*/
884IXML_CDATASection *
885ixmlNode_cloneCDATASect( IN IXML_CDATASection * nodeptr )
886{
887    IXML_CDATASection *newCDATA = NULL;
888    IXML_Node *newNode;
889    IXML_Node *srcNode;
890
891    assert( nodeptr != NULL );
892    newCDATA =
893        ( IXML_CDATASection * ) malloc( sizeof( IXML_CDATASection ) );
894    if( newCDATA != NULL ) {
895        newNode = ( IXML_Node * ) newCDATA;
896        ixmlNode_init( newNode );
897
898        srcNode = ( IXML_Node * ) nodeptr;
899        ixmlNode_setNodeName( newNode, srcNode->nodeName );
900        ixmlNode_setNodeValue( newNode, srcNode->nodeValue );
901        newNode->nodeType = eCDATA_SECTION_NODE;
902    }
903
904    return newCDATA;
905}
906
907/*================================================================
908*   ixmlNode_cloneElement
909*       returns a clone of element node
910*       Internal to parser only.
911*
912*=================================================================*/
913IXML_Element *
914ixmlNode_cloneElement( IN IXML_Element * nodeptr )
915{
916    IXML_Element *newElement;
917    IXML_Node *elementNode;
918    IXML_Node *srcNode;
919    int rc;
920
921    assert( nodeptr != NULL );
922
923    newElement = ( IXML_Element * ) malloc( sizeof( IXML_Element ) );
924    if( newElement == NULL ) {
925        return NULL;
926    }
927
928    ixmlElement_init( newElement );
929    rc = ixmlElement_setTagName( newElement, nodeptr->tagName );
930    if( rc != IXML_SUCCESS ) {
931        ixmlElement_free( newElement );
932    }
933
934    elementNode = ( IXML_Node * ) newElement;
935    srcNode = ( IXML_Node * ) nodeptr;
936    rc = ixmlNode_setNodeName( elementNode, srcNode->nodeName );
937    if( rc != IXML_SUCCESS ) {
938        ixmlElement_free( newElement );
939    }
940
941    rc = ixmlNode_setNodeValue( elementNode, srcNode->nodeValue );
942    if( rc != IXML_SUCCESS ) {
943        ixmlElement_free( newElement );
944    }
945
946    rc = ixmlNode_setNamespaceURI( elementNode, srcNode->namespaceURI );
947    if( rc != IXML_SUCCESS ) {
948        ixmlElement_free( newElement );
949    }
950
951    rc = ixmlNode_setPrefix( elementNode, srcNode->prefix );
952    if( rc != IXML_SUCCESS ) {
953        ixmlElement_free( newElement );
954    }
955
956    rc = ixmlNode_setLocalName( elementNode, srcNode->localName );
957    if( rc != IXML_SUCCESS ) {
958        ixmlElement_free( newElement );
959    }
960
961    elementNode->nodeType = eELEMENT_NODE;
962
963    return newElement;
964
965}
966
967/*================================================================
968*   ixmlNode_cloneDoc
969*       Returns a clone of document node
970*       Internal to parser only.
971*
972*=================================================================*/
973IXML_Document *
974ixmlNode_cloneDoc( IN IXML_Document * nodeptr )
975{
976    IXML_Document *newDoc;
977    IXML_Node *docNode;
978    int rc;
979
980    assert( nodeptr != NULL );
981    newDoc = ( IXML_Document * ) malloc( sizeof( IXML_Document ) );
982    if( newDoc == NULL ) {
983        return NULL;
984    }
985
986    ixmlDocument_init( newDoc );
987    docNode = ( IXML_Node * ) newDoc;
988
989    rc = ixmlNode_setNodeName( docNode, DOCUMENTNODENAME );
990    if( rc != IXML_SUCCESS ) {
991        ixmlDocument_free( newDoc );
992        return NULL;
993    }
994
995    newDoc->n.nodeType = eDOCUMENT_NODE;
996
997    return newDoc;
998
999}
1000
1001/*================================================================
1002*   ixmlNode_cloneAttr
1003*       Returns a clone of attribute node
1004*       Internal to parser only
1005*
1006*=================================================================*/
1007IXML_Attr *
1008ixmlNode_cloneAttr( IN IXML_Attr * nodeptr )
1009{
1010    IXML_Attr *newAttr;
1011    IXML_Node *attrNode;
1012    IXML_Node *srcNode;
1013    int rc;
1014
1015    assert( nodeptr != NULL );
1016    newAttr = ( IXML_Attr * ) malloc( sizeof( IXML_Attr ) );
1017    if( newAttr == NULL ) {
1018        return NULL;
1019    }
1020
1021    ixmlAttr_init( newAttr );
1022    attrNode = ( IXML_Node * ) newAttr;
1023    srcNode = ( IXML_Node * ) nodeptr;
1024
1025    rc = ixmlNode_setNodeName( attrNode, srcNode->nodeName );
1026    if( rc != IXML_SUCCESS ) {
1027        ixmlAttr_free( newAttr );
1028        return NULL;
1029    }
1030
1031    rc = ixmlNode_setNodeValue( attrNode, srcNode->nodeValue );
1032    if( rc != IXML_SUCCESS ) {
1033        ixmlAttr_free( newAttr );
1034        return NULL;
1035    }
1036    //check to see whether we need to split prefix and localname for attribute
1037    rc = ixmlNode_setNamespaceURI( attrNode, srcNode->namespaceURI );
1038    if( rc != IXML_SUCCESS ) {
1039        ixmlAttr_free( newAttr );
1040        return NULL;
1041    }
1042
1043    rc = ixmlNode_setPrefix( attrNode, srcNode->prefix );
1044    if( rc != IXML_SUCCESS ) {
1045        ixmlAttr_free( newAttr );
1046        return NULL;
1047    }
1048
1049    rc = ixmlNode_setLocalName( attrNode, srcNode->localName );
1050    if( rc != IXML_SUCCESS ) {
1051        ixmlAttr_free( newAttr );
1052        return NULL;
1053    }
1054
1055    attrNode->nodeType = eATTRIBUTE_NODE;
1056
1057    return newAttr;
1058}
1059
1060/*================================================================
1061*   ixmlNode_cloneAttrDirect
1062*       Return a clone of attribute node, with specified field set
1063*       to TRUE.
1064*
1065*=================================================================*/
1066IXML_Attr *
1067ixmlNode_cloneAttrDirect( IN IXML_Attr * nodeptr )
1068{
1069
1070    IXML_Attr *newAttr;
1071
1072    assert( nodeptr != NULL );
1073
1074    newAttr = ixmlNode_cloneAttr( nodeptr );
1075    if( newAttr != NULL ) {
1076        newAttr->specified = TRUE;
1077    }
1078
1079    return newAttr;
1080}
1081
1082void
1083ixmlNode_setSiblingNodesParent( IXML_Node * nodeptr )
1084{
1085    IXML_Node *parentNode = nodeptr->parentNode;
1086    IXML_Node *nextptr = nodeptr->nextSibling;
1087
1088    while( nextptr != NULL ) {
1089        nextptr->parentNode = parentNode;
1090        nextptr = nextptr->nextSibling;
1091    }
1092}
1093
1094/*================================================================
1095*   ixmlNode_cloneNodeTreeRecursive
1096*       recursive functions that clones node tree of nodeptr.
1097*       Internal to parser only.
1098*
1099*=================================================================*/
1100IXML_Node *
1101ixmlNode_cloneNodeTreeRecursive( IN IXML_Node * nodeptr,
1102                                 IN BOOL deep )
1103{
1104    IXML_Node *newNode = NULL;
1105    IXML_Element *newElement;
1106    IXML_Attr *newAttr = NULL;
1107    IXML_CDATASection *newCDATA = NULL;
1108    IXML_Document *newDoc;
1109    IXML_Node *nextSib;
1110
1111    if( nodeptr != NULL ) {
1112        switch ( nodeptr->nodeType ) {
1113            case eELEMENT_NODE:
1114                newElement =
1115                    ixmlNode_cloneElement( ( IXML_Element * ) nodeptr );
1116                newElement->n.firstAttr =
1117                    ixmlNode_cloneNodeTreeRecursive( nodeptr->firstAttr,
1118                                                     deep );
1119                if( deep ) {
1120                    newElement->n.firstChild =
1121                        ixmlNode_cloneNodeTreeRecursive( nodeptr->
1122                                                         firstChild,
1123                                                         deep );
1124                    if( newElement->n.firstChild != NULL ) {
1125                        ( newElement->n.firstChild )->parentNode =
1126                            ( IXML_Node * ) newElement;
1127                        ixmlNode_setSiblingNodesParent( newElement->n.
1128                                                        firstChild );
1129                    }
1130                    nextSib =
1131                        ixmlNode_cloneNodeTreeRecursive( nodeptr->
1132                                                         nextSibling,
1133                                                         deep );
1134                    newElement->n.nextSibling = nextSib;
1135                    if( nextSib != NULL ) {
1136                        nextSib->prevSibling = ( IXML_Node * ) newElement;
1137                    }
1138                }
1139
1140                newNode = ( IXML_Node * ) newElement;
1141                break;
1142
1143            case eATTRIBUTE_NODE:
1144                newAttr = ixmlNode_cloneAttr( ( IXML_Attr * ) nodeptr );
1145                nextSib =
1146                    ixmlNode_cloneNodeTreeRecursive( nodeptr->nextSibling,
1147                                                     deep );
1148                newAttr->n.nextSibling = nextSib;
1149
1150                if( nextSib != NULL ) {
1151                    nextSib->prevSibling = ( IXML_Node * ) newAttr;
1152                }
1153                newNode = ( IXML_Node * ) newAttr;
1154                break;
1155
1156            case eTEXT_NODE:
1157                newNode = ixmlNode_cloneTextNode( nodeptr );
1158                break;
1159
1160            case eCDATA_SECTION_NODE:
1161                newCDATA =
1162                    ixmlNode_cloneCDATASect( ( IXML_CDATASection * )
1163                                             nodeptr );
1164                newNode = ( IXML_Node * ) newCDATA;
1165                break;
1166
1167            case eDOCUMENT_NODE:
1168                newDoc = ixmlNode_cloneDoc( ( IXML_Document * ) nodeptr );
1169                newNode = ( IXML_Node * ) newDoc;
1170                if( deep ) {
1171                    newNode->firstChild =
1172                        ixmlNode_cloneNodeTreeRecursive( nodeptr->
1173                                                         firstChild,
1174                                                         deep );
1175                    if( newNode->firstChild != NULL ) {
1176                        newNode->firstChild->parentNode = newNode;
1177                    }
1178                }
1179
1180                break;
1181
1182            case eINVALID_NODE:
1183            case eENTITY_REFERENCE_NODE:
1184            case eENTITY_NODE:
1185            case ePROCESSING_INSTRUCTION_NODE:
1186            case eCOMMENT_NODE:
1187            case eDOCUMENT_TYPE_NODE:
1188            case eDOCUMENT_FRAGMENT_NODE:
1189            case eNOTATION_NODE:
1190                break;
1191        }
1192    }
1193
1194    return newNode;
1195}
1196
1197/*================================================================
1198*   ixmlNode_cloneNodeTree
1199*       clones a node tree.
1200*       Internal to parser only.
1201*
1202*=================================================================*/
1203IXML_Node *
1204ixmlNode_cloneNodeTree( IN IXML_Node * nodeptr,
1205                        IN BOOL deep )
1206{
1207    IXML_Node *newNode = NULL;
1208    IXML_Element *newElement;
1209    IXML_Node *childNode;
1210
1211    assert( nodeptr != NULL );
1212
1213    switch ( nodeptr->nodeType ) {
1214        case eELEMENT_NODE:
1215            newElement =
1216                ixmlNode_cloneElement( ( IXML_Element * ) nodeptr );
1217            newElement->n.firstAttr =
1218                ixmlNode_cloneNodeTreeRecursive( nodeptr->firstAttr,
1219                                                 deep );
1220            if( deep ) {
1221                newElement->n.firstChild =
1222                    ixmlNode_cloneNodeTreeRecursive( nodeptr->firstChild,
1223                                                     deep );
1224                childNode = newElement->n.firstChild;
1225                while( childNode != NULL ) {
1226                    childNode->parentNode = ( IXML_Node * ) newElement;
1227                    childNode = childNode->nextSibling;
1228                }
1229                newElement->n.nextSibling = NULL;
1230            }
1231
1232            newNode = ( IXML_Node * ) newElement;
1233            break;
1234
1235        case eATTRIBUTE_NODE:
1236        case eTEXT_NODE:
1237        case eCDATA_SECTION_NODE:
1238        case eDOCUMENT_NODE:
1239            newNode = ixmlNode_cloneNodeTreeRecursive( nodeptr, deep );
1240            break;
1241
1242        case eINVALID_NODE:
1243        case eENTITY_REFERENCE_NODE:
1244        case eENTITY_NODE:
1245        case ePROCESSING_INSTRUCTION_NODE:
1246        case eCOMMENT_NODE:
1247        case eDOCUMENT_TYPE_NODE:
1248        case eDOCUMENT_FRAGMENT_NODE:
1249        case eNOTATION_NODE:
1250            break;
1251    }
1252
1253    // by spec, the duplicate node has no parent
1254    newNode->parentNode = NULL;
1255
1256    return newNode;
1257}
1258
1259/*================================================================
1260*   ixmlNode_cloneNode
1261*       Clones a node, if deep==TRUE, clones subtree under nodeptr.
1262*       External function.
1263*   Returns:
1264*       the cloned node or NULL if error occurs.
1265*
1266*=================================================================*/
1267IXML_Node *
1268ixmlNode_cloneNode( IN IXML_Node * nodeptr,
1269                    IN BOOL deep )
1270{
1271
1272    IXML_Node *newNode;
1273    IXML_Attr *newAttrNode;
1274
1275    if( nodeptr == NULL ) {
1276        return NULL;
1277    }
1278
1279    switch ( nodeptr->nodeType ) {
1280        case eATTRIBUTE_NODE:
1281            newAttrNode =
1282                ixmlNode_cloneAttrDirect( ( IXML_Attr * ) nodeptr );
1283            return ( IXML_Node * ) newAttrNode;
1284            break;
1285
1286        default:
1287            newNode = ixmlNode_cloneNodeTree( nodeptr, deep );
1288            return newNode;
1289            break;
1290    }
1291
1292}
1293
1294/*================================================================
1295*   ixmlNode_getChildNodes
1296*       Returns a IXML_NodeList of all the child nodes of nodeptr.
1297*       External function.
1298*
1299*=================================================================*/
1300IXML_NodeList *
1301ixmlNode_getChildNodes( IN IXML_Node * nodeptr )
1302{
1303    IXML_Node *tempNode;
1304    IXML_NodeList *newNodeList;
1305    int rc;
1306
1307    if( nodeptr == NULL ) {
1308        return NULL;
1309    }
1310
1311    newNodeList = ( IXML_NodeList * ) malloc( sizeof( IXML_NodeList ) );
1312    if( newNodeList == NULL ) {
1313        return NULL;
1314    }
1315
1316    ixmlNodeList_init( newNodeList );
1317
1318    tempNode = nodeptr->firstChild;
1319    while( tempNode != NULL ) {
1320        rc = ixmlNodeList_addToNodeList( &newNodeList, tempNode );
1321        if( rc != IXML_SUCCESS ) {
1322            ixmlNodeList_free( newNodeList );
1323            return NULL;
1324        }
1325
1326        tempNode = tempNode->nextSibling;
1327    }
1328    return newNodeList;
1329}
1330
1331/*================================================================
1332*   ixmlNode_getAttributes
1333*       returns a namedNodeMap of attributes of nodeptr
1334*       External function.
1335*   Returns:
1336*
1337*=================================================================*/
1338IXML_NamedNodeMap *
1339ixmlNode_getAttributes( IN IXML_Node * nodeptr )
1340{
1341    IXML_NamedNodeMap *returnNamedNodeMap = NULL;
1342    IXML_Node *tempNode;
1343    int rc;
1344
1345    if( nodeptr == NULL ) {
1346        return NULL;
1347    }
1348
1349    if( nodeptr->nodeType == eELEMENT_NODE ) {
1350        returnNamedNodeMap =
1351            ( IXML_NamedNodeMap * ) malloc( sizeof( IXML_NamedNodeMap ) );
1352        if( returnNamedNodeMap == NULL ) {
1353            return NULL;
1354        }
1355
1356        ixmlNamedNodeMap_init( returnNamedNodeMap );
1357
1358        tempNode = nodeptr->firstAttr;
1359        while( tempNode != NULL ) {
1360            rc = ixmlNamedNodeMap_addToNamedNodeMap( &returnNamedNodeMap,
1361                                                     tempNode );
1362            if( rc != IXML_SUCCESS ) {
1363                ixmlNamedNodeMap_free( returnNamedNodeMap );
1364                return NULL;
1365            }
1366
1367            tempNode = tempNode->nextSibling;
1368        }
1369        return returnNamedNodeMap;
1370    } else {                    // if not an ELEMENT_NODE
1371        return NULL;
1372    }
1373}
1374
1375/*================================================================
1376*   ixmlNode_hasChildNodes
1377*       External function.
1378*
1379*=================================================================*/
1380BOOL
1381ixmlNode_hasChildNodes( IXML_Node * nodeptr )
1382{
1383    if( nodeptr == NULL ) {
1384        return FALSE;
1385    }
1386
1387    return ( nodeptr->firstChild != NULL );
1388
1389}
1390
1391/*================================================================
1392*   ixmlNode_hasAttributes
1393*       External function.
1394*
1395*=================================================================*/
1396BOOL
1397ixmlNode_hasAttributes( IXML_Node * nodeptr )
1398{
1399    if( nodeptr != NULL ) {
1400        if( ( nodeptr->nodeType == eELEMENT_NODE )
1401            && ( nodeptr->firstAttr != NULL ) ) {
1402            return TRUE;
1403        }
1404    }
1405    return FALSE;
1406
1407}
1408
1409/*================================================================
1410*   ixmlNode_getElementsByTagNameRecursive
1411*       Recursively traverse the whole tree, search for element
1412*       with the given tagname.
1413*       Internal to parser.
1414*
1415*=================================================================*/
1416void
1417ixmlNode_getElementsByTagNameRecursive( IN IXML_Node * n,
1418                                        IN char *tagname,
1419                                        OUT IXML_NodeList ** list )
1420{
1421    const char *name;
1422
1423    if( n != NULL ) {
1424        if( ixmlNode_getNodeType( n ) == eELEMENT_NODE ) {
1425            name = ixmlNode_getNodeName( n );
1426            if( strcmp( tagname, name ) == 0
1427                || strcmp( tagname, "*" ) == 0 ) {
1428                ixmlNodeList_addToNodeList( list, n );
1429            }
1430        }
1431
1432        ixmlNode_getElementsByTagNameRecursive( ixmlNode_getFirstChild
1433                                                ( n ), tagname, list );
1434        ixmlNode_getElementsByTagNameRecursive( ixmlNode_getNextSibling
1435                                                ( n ), tagname, list );
1436    }
1437
1438}
1439
1440/*================================================================
1441*   ixmlNode_getElementsByTagName
1442*       Returns a nodeList of all descendant Elements with a given
1443*       tagName, in the order in which they are encountered in a
1444*       traversal of this element tree.
1445*       External function.
1446*
1447*=================================================================*/
1448void
1449ixmlNode_getElementsByTagName( IN IXML_Node * n,
1450                               IN char *tagname,
1451                               OUT IXML_NodeList ** list )
1452{
1453    const char *name;
1454
1455    assert( n != NULL && tagname != NULL );
1456
1457    if( ixmlNode_getNodeType( n ) == eELEMENT_NODE ) {
1458        name = ixmlNode_getNodeName( n );
1459        if( strcmp( tagname, name ) == 0 || strcmp( tagname, "*" ) == 0 ) {
1460            ixmlNodeList_addToNodeList( list, n );
1461        }
1462    }
1463
1464    ixmlNode_getElementsByTagNameRecursive( ixmlNode_getFirstChild( n ),
1465                                            tagname, list );
1466
1467}
1468
1469/*================================================================
1470*   ixmlNode_getElementsByTagNameNSRecursive
1471*	    Internal function to parser.
1472*
1473*
1474*=================================================================*/
1475void
1476ixmlNode_getElementsByTagNameNSRecursive( IN IXML_Node * n,
1477                                          IN char *namespaceURI,
1478                                          IN char *localName,
1479                                          OUT IXML_NodeList ** list )
1480{
1481    const DOMString nsURI;
1482    const DOMString name;
1483
1484    if( n != NULL ) {
1485        if( ixmlNode_getNodeType( n ) == eELEMENT_NODE ) {
1486            name = ixmlNode_getLocalName( n );
1487            nsURI = ixmlNode_getNamespaceURI( n );
1488
1489            if( ( name != NULL ) && ( nsURI != NULL ) &&
1490                ( strcmp( namespaceURI, nsURI ) == 0
1491                  || strcmp( namespaceURI, "*" ) == 0 )
1492                && ( strcmp( name, localName ) == 0
1493                     || strcmp( localName, "*" ) == 0 ) ) {
1494                ixmlNodeList_addToNodeList( list, n );
1495            }
1496        }
1497
1498        ixmlNode_getElementsByTagNameNSRecursive( ixmlNode_getFirstChild
1499                                                  ( n ), namespaceURI,
1500                                                  localName, list );
1501        ixmlNode_getElementsByTagNameNSRecursive( ixmlNode_getNextSibling
1502                                                  ( n ), namespaceURI,
1503                                                  localName, list );
1504    }
1505
1506}
1507
1508/*================================================================
1509*   ixmlNode_getElementsByTagNameNS
1510*       Returns a nodeList of all the descendant Elements with a given
1511*       local name and namespace URI in the order in which they are
1512*       encountered in a preorder traversal of this Elememt tree.
1513*		External function.
1514*
1515*=================================================================*/
1516void
1517ixmlNode_getElementsByTagNameNS( IN IXML_Node * n,
1518                                 IN char *namespaceURI,
1519                                 IN char *localName,
1520                                 OUT IXML_NodeList ** list )
1521{
1522    const DOMString nsURI;
1523    const DOMString name;
1524
1525    assert( n != NULL && namespaceURI != NULL && localName != NULL );
1526
1527    if( ixmlNode_getNodeType( n ) == eELEMENT_NODE ) {
1528        name = ixmlNode_getLocalName( n );
1529        nsURI = ixmlNode_getNamespaceURI( n );
1530
1531        if( ( name != NULL ) && ( nsURI != NULL ) &&
1532            ( strcmp( namespaceURI, nsURI ) == 0
1533              || strcmp( namespaceURI, "*" ) == 0 )
1534            && ( strcmp( name, localName ) == 0
1535                 || strcmp( localName, "*" ) == 0 ) ) {
1536            ixmlNodeList_addToNodeList( list, n );
1537        }
1538    }
1539
1540    ixmlNode_getElementsByTagNameNSRecursive( ixmlNode_getFirstChild( n ),
1541                                              namespaceURI, localName,
1542                                              list );
1543
1544}
1545
1546/*================================================================
1547*   ixmlNode_setNodeName
1548*       Internal to parser only.
1549*
1550*=================================================================*/
1551int
1552ixmlNode_setNodeName( IN IXML_Node * node,
1553                      IN DOMString qualifiedName )
1554{
1555    int rc = IXML_SUCCESS;
1556
1557    assert( node != NULL );
1558
1559    if( node->nodeName != NULL ) {
1560        free( node->nodeName );
1561        node->nodeName = NULL;
1562    }
1563
1564    if( qualifiedName != NULL ) {
1565        // set the name part
1566        node->nodeName = strdup( qualifiedName );
1567        if( node->nodeName == NULL ) {
1568            return IXML_INSUFFICIENT_MEMORY;
1569        }
1570
1571        rc = Parser_setNodePrefixAndLocalName( node );
1572        if( rc != IXML_SUCCESS ) {
1573            free( node->nodeName );
1574        }
1575    }
1576
1577    return rc;
1578}
1579
1580/*================================================================
1581*   ixmlNode_setNodeProperties
1582*       Internal to parser only.
1583*
1584*=================================================================*/
1585int
1586ixmlNode_setNodeProperties( IN IXML_Node * destNode,
1587                            IN IXML_Node * src )
1588{
1589
1590    int rc;
1591
1592    assert( destNode != NULL || src != NULL );
1593
1594    rc = ixmlNode_setNodeValue( destNode, src->nodeValue );
1595    if( rc != IXML_SUCCESS ) {
1596        goto ErrorHandler;
1597    }
1598
1599    rc = ixmlNode_setLocalName( destNode, src->localName );
1600    if( rc != IXML_SUCCESS ) {
1601        goto ErrorHandler;
1602    }
1603
1604    rc = ixmlNode_setPrefix( destNode, src->prefix );
1605    if( rc != IXML_SUCCESS ) {
1606        goto ErrorHandler;
1607    }
1608    // set nodetype
1609    destNode->nodeType = src->nodeType;
1610
1611    return IXML_SUCCESS;
1612
1613  ErrorHandler:
1614    if( destNode->nodeName != NULL ) {
1615        free( destNode->nodeName );
1616        destNode->nodeName = NULL;
1617    }
1618    if( destNode->nodeValue != NULL ) {
1619        free( destNode->nodeValue );
1620        destNode->nodeValue = NULL;
1621    }
1622    if( destNode->localName != NULL ) {
1623        free( destNode->localName );
1624        destNode->localName = NULL;
1625    }
1626
1627    return IXML_INSUFFICIENT_MEMORY;
1628}
1629