blob: ee89df5cccf5bcb88d4e845300f6c966ec2c4daa [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001///////////////////////////////////////////////////////////////////////////
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 "xmlparser.h"
33
34
35/*================================================================
36* XmlElement_Init
37* Initializes an element node.
38* External function.
39*
40*=================================================================*/
41void
42XmlElementInit( XmlElement * element )
43{
44 if ( element != NULL )
45 {
46 memset( element, 0, sizeof( XmlElement ) );
47 element->node.nodeType = XML_ELEMENT_NODE;
48 }
49}
50
51/*================================================================
52* XmlElementGetTagName
53* Gets the element node's tagName
54* External function.
55*
56*=================================================================*/
57const char *
58XmlElementGetTagName( XmlElement * element )
59{
60
61 if ( element != NULL )
62 {
63 return element->tagName;
64 }
65 else
66 {
67 return NULL;
68 }
69}
70
71/*================================================================
72* XmlElementSetTagName
73* Sets the given element's tagName.
74* Parameters:
75* tagName: new tagName for the element.
76*
77*=================================================================*/
78int
79XmlElementSetTagName(
80 Pool * pool,
81 XmlElement * element,
82 const char *tagName )
83{
84 int rc = XML_OK;
85
86// assert( ( element != NULL ) && ( tagName != NULL ) );
87 if ( ( element == NULL ) || ( tagName == NULL ) )
88 {
89 return XML_FAILED;
90 }
91
92 if ( element->tagName != NULL )
93 {
94 PFREE( element->tagName );
95 }
96
97 element->tagName = PSTRDUP( tagName );
98 if ( element->tagName == NULL )
99 {
100 rc = XML_INSUFFICIENT_MEMORY;
101 }
102
103 return rc;
104
105}
106
107/*=========================================================================
108* XmlElementGetAttribute
109* Retrievea an attribute value by name.
110* External function.
111* Parameters:
112* name: the name of the attribute to retrieve.
113* Return Values:
114* attribute value as a string, or the empty string if that attribute
115* does not have a specified value.
116*
117*========================================================================*/
118char *
119XmlElementGetAttribute( XmlElement * element,
120 const char * name )
121{
122 XmlNode * attrNode;
123
124 if ( ( element == NULL ) || ( name == NULL ) )
125 {
126 return NULL;
127 }
128
129 attrNode = element->node.firstAttr;
130 while ( attrNode != NULL )
131 {
132 if ( strcmp( attrNode->nodeName, name ) == 0 ) // found it
133 {
134 return attrNode->nodeValue;
135 }
136 else
137 {
138 attrNode = attrNode->nextSibling;
139 }
140 }
141
142 return NULL;
143}
144
145/*======================================================================
146* XmlElementSetAttribute
147* Adds a new attribute. If an attribute with that name is already
148* present in the element, its value is changed to be that of the value
149* parameter. If not, a new attribute is inserted into the element.
150*
151* External function.
152* Parameters:
153* name: the name of the attribute to create or alter.
154* value: value to set in string form
155* Return Values:
156* XML_OK or failure code.
157*=======================================================================*/
158int
159XmlElementSetAttribute(
160 Pool * pool,
161 XmlElement * element,
162 const char *name,
163 const char *value )
164{
165 XmlNode * attrNode;
166 XmlAttribute *newAttrNode;
167 short errCode = XML_OK;
168
169 if ( ( element == NULL ) || ( name == NULL ) || ( value == NULL ) )
170 {
171 errCode = XML_INVALID_PARAMETER;
172 goto ErrorHandler;
173 }
174
175 if ( XmlParserIsValidXmlName( name ) == FALSE )
176 {
177 errCode = XML_INVALID_CHARACTER_ERR;
178 goto ErrorHandler;
179 }
180
181 attrNode = element->node.firstAttr;
182 while ( attrNode != NULL )
183 {
184 if ( strcmp( attrNode->nodeName, name ) == 0 )
185 {
186 break; //found it
187 }
188 else
189 {
190 attrNode = attrNode->nextSibling;
191 }
192 }
193
194 if ( attrNode == NULL ) // add a new attribute
195 {
196 errCode =
197 XmlDocCreateAttributeEx(
198#ifdef USE_CWMP_MEMORY_POOL
199 pool ,
200#endif
201
202 ( XmlDocument * ) element->node.
203 ownerDocument, name,
204 &newAttrNode );
205 if ( errCode != XML_OK )
206 {
207 goto ErrorHandler;
208 }
209
210 attrNode = ( XmlNode * ) newAttrNode;
211
212 attrNode->nodeValue = XmlStrduptrim(
213#ifdef USE_CWMP_MEMORY_POOL
214 pool ,
215#endif
216 value );
217 if ( attrNode->nodeValue == NULL )
218 {
219 XmlAttrFree(
220#ifdef USE_CWMP_MEMORY_POOL
221 pool ,
222#endif
223 newAttrNode );
224 errCode = XML_INSUFFICIENT_MEMORY;
225 goto ErrorHandler;
226 }
227
228 errCode =
229 XmlElementSetAttributeNode( element, newAttrNode, NULL );
230 if ( errCode != XML_OK )
231 {
232 XmlAttrFree(
233#ifdef USE_CWMP_MEMORY_POOL
234 pool ,
235#endif
236 newAttrNode );
237 goto ErrorHandler;
238 }
239
240 }
241 else
242 {
243 if ( attrNode->nodeValue != NULL ) // attribute name has a value already
244 {
245 PFREE( attrNode->nodeValue );
246 }
247
248 attrNode->nodeValue = XmlStrduptrim(
249#ifdef USE_CWMP_MEMORY_POOL
250 pool ,
251#endif
252 value );
253 if ( attrNode->nodeValue == NULL )
254 {
255 errCode = XML_INSUFFICIENT_MEMORY;
256 }
257 }
258
259ErrorHandler:
260 return errCode;
261}
262
263/*================================================================
264* XmlElementRemoveAttribute
265* Removes an attribute value by name. The attribute node is
266* not removed.
267* External function.
268* Parameters:
269* name: the name of the attribute to remove.
270* Return Values:
271* XML_OK or error code.
272*
273*=================================================================*/
274int
275XmlElementRemoveAttribute(
276 Pool * pool,
277 XmlElement * element,
278 const char *name )
279{
280
281 XmlNode * attrNode;
282
283 if ( ( element == NULL ) || ( name == NULL ) )
284 {
285 return XML_INVALID_PARAMETER;
286 }
287
288 attrNode = element->node.firstAttr;
289 while ( attrNode != NULL )
290 {
291 if ( strcmp( attrNode->nodeName, name ) == 0 )
292 {
293 break; //found it
294 }
295 else
296 {
297 attrNode = attrNode->nextSibling;
298 }
299 }
300
301 if ( attrNode != NULL ) // has the attribute
302 {
303 if ( attrNode->nodeValue != NULL )
304 {
305 PFREE( attrNode->nodeValue );
306 attrNode->nodeValue = NULL;
307 }
308 }
309
310 return XML_OK;
311}
312
313/*================================================================
314* XmlElementGetAttributeNode
315* Retrieve an attribute node by name.
316* External function.
317* Parameters:
318* name: the name(nodeName) of the attribute to retrieve.
319* Return Value:
320* The attr node with the specified name (nodeName) or NULL if
321* there is no such attribute.
322*
323*=================================================================*/
324XmlAttribute *
325XmlElementGetAttributeNode( XmlElement * element,
326 IN char *name )
327{
328
329 XmlNode * attrNode;
330
331 if ( ( element == NULL ) || ( name == NULL ) )
332 {
333 return NULL;
334 }
335
336 attrNode = element->node.firstAttr;
337 while ( attrNode != NULL )
338 {
339 if ( strcmp( attrNode->nodeName, name ) == 0 ) // found it
340 {
341 break;
342 }
343 else
344 {
345 attrNode = attrNode->nextSibling;
346 }
347 }
348
349 return ( XmlAttribute * ) attrNode;
350
351}
352
353/*==========================================================================
354* XmlElementSetAttributeNode
355* Adds a new attribute node. If an attribute with that name(nodeName)
356* is already present in the element, it is replaced by the new one.
357* External function.
358* Parameters:
359* The attr node to add to the attribute list.
360* Return Value:
361* if newAttr replaces an existing attribute, the replaced
362* attr node is returned, otherwise NULL is returned.
363*
364*===========================================================================*/
365int
366XmlElementSetAttributeNode( XmlElement * element,
367 XmlAttribute * newAttr,
368 OUT XmlAttribute ** rtAttr )
369{
370
371 XmlNode * attrNode;
372 XmlNode * node;
373 XmlNode * nextAttr = NULL;
374 XmlNode * prevAttr = NULL;
375 XmlNode * preSib;
376 XmlNode * nextSib;
377
378 if ( ( element == NULL ) || ( newAttr == NULL ) )
379 {
380 return XML_INVALID_PARAMETER;
381 }
382
383 if ( newAttr->node.ownerDocument != element->node.ownerDocument )
384 {
385 return XML_WRONG_DOCUMENT_ERR;
386 }
387
388 if ( newAttr->ownerElement != NULL )
389 {
390 return XML_INUSE_ATTRIBUTE_ERR;
391 }
392
393 newAttr->ownerElement = element;
394 node = ( XmlNode * ) newAttr;
395
396 attrNode = element->node.firstAttr;
397 while ( attrNode != NULL )
398 {
399 if ( strcmp( attrNode->nodeName, node->nodeName ) == 0 )
400 {
401 break; //found it
402 }
403 else
404 {
405 attrNode = attrNode->nextSibling;
406 }
407 }
408
409 if ( attrNode != NULL ) // already present, will replace by newAttr
410 {
411 preSib = attrNode->prevSibling;
412 nextSib = attrNode->nextSibling;
413
414 if ( preSib != NULL )
415 {
416 preSib->nextSibling = node;
417 }
418
419 if ( nextSib != NULL )
420 {
421 nextSib->prevSibling = node;
422 }
423
424 if ( element->node.firstAttr == attrNode )
425 {
426 element->node.firstAttr = node;
427 }
428
429 if ( rtAttr != NULL )
430 {
431 *rtAttr = ( XmlAttribute * ) attrNode;
432 }
433 }
434 else // add this attribute
435 {
436 if ( element->node.firstAttr != NULL )
437 {
438 prevAttr = element->node.firstAttr;
439 nextAttr = prevAttr->nextSibling;
440 while ( nextAttr != NULL )
441 {
442 prevAttr = nextAttr;
443 nextAttr = prevAttr->nextSibling;
444 }
445 prevAttr->nextSibling = node;
446 node->prevSibling = prevAttr;
447 }
448 else // this is the first attribute node
449 {
450 element->node.firstAttr = node;
451 node->prevSibling = NULL;
452 node->nextSibling = NULL;
453 }
454
455 if ( rtAttr != NULL )
456 {
457 *rtAttr = NULL;
458 }
459 }
460
461 return XML_OK;
462}
463
464/*=======================================================================
465* XmlElementFindAttributeNode
466* Find a attribute node whose contents are the same as the oldAttr.
467* Internal only to parser.
468* Parameter:
469* oldAttr: the attribute node to match
470* Return:
471* if found it, the attribute node is returned,
472* otherwise, return NULL.
473*
474*========================================================================*/
475XmlNode *
476XmlElementFindAttributeNode( XmlElement * element,
477 XmlAttribute * oldAttr )
478{
479 XmlNode * attrNode;
480 XmlNode * oldAttrNode = ( XmlNode * ) oldAttr;
481
482 assert( ( element != NULL ) && ( oldAttr != NULL ) );
483
484 attrNode = element->node.firstAttr;
485 while ( attrNode != NULL ) // parentNode, prevSib, nextSib and ownerDocument doesn't matter
486 {
487 if ( XmlNodeCompare( attrNode, oldAttrNode ) == TRUE )
488 {
489 break; //found it
490 }
491 else
492 {
493 attrNode = attrNode->nextSibling;
494 }
495 }
496
497 return attrNode;
498
499}
500
501/*==================================================================
502* XmlElementRemoveAttributeNode
503* Removes the specified attribute node.
504* External function.
505*
506* Parameters:
507* oldAttr: the attr node to remove from the attribute list.
508*
509* Return Value:
510* XML_OK or failure
511*
512*===================================================================*/
513int
514XmlElementRemoveAttributeNode( XmlElement * element,
515 XmlAttribute * oldAttr,
516 OUT XmlAttribute ** rtAttr )
517{
518 XmlNode * attrNode;
519 XmlNode * preSib;
520 XmlNode * nextSib;
521
522 if ( ( element == NULL ) || ( oldAttr == NULL ) )
523 {
524 return XML_INVALID_PARAMETER;
525 }
526
527 attrNode = XmlElementFindAttributeNode( element, oldAttr );
528 if ( attrNode != NULL ) // has the attribute
529 {
530 preSib = attrNode->prevSibling;
531 nextSib = attrNode->nextSibling;
532
533 if ( preSib != NULL )
534 {
535 preSib->nextSibling = nextSib;
536 }
537
538 if ( nextSib != NULL )
539 {
540 nextSib->prevSibling = preSib;
541 }
542
543 if ( element->node.firstAttr == attrNode )
544 {
545 element->node.firstAttr = nextSib;
546 }
547
548 attrNode->parentNode = 0;
549 attrNode->prevSibling = 0 ;
550 attrNode->nextSibling = 0;
551 *rtAttr = ( XmlAttribute * ) attrNode;
552 return XML_OK;
553
554 }
555 else
556 {
557 return XML_NOT_FOUND_ERR;
558 }
559
560}
561
562/*================================================================
563* XmlElementGetElementsByTagName
564* Returns a nodeList of all descendant Elements with a given
565* tag name, in the order in which they are encountered in a preorder
566* traversal of this element tree.
567* External function.
568*
569* Parameters:
570* tagName: the name of the tag to match on. The special value "*"
571* matches all tags.
572*
573* Return Value:
574* a nodeList of matching element nodes.
575*
576*=================================================================*/
577XmlNodeList *
578XmlElementGetElementsByTagName(
579 Pool * pool,
580 XmlElement * element,
581 IN char *tagName )
582{
583 XmlNodeList *returnNodeList = NULL;
584
585 if ( ( element != NULL ) && ( tagName != NULL ) )
586 {
587 XmlNodeGetElementsByTagName(
588#ifdef USE_CWMP_MEMORY_POOL
589 pool ,
590#endif
591
592 ( XmlNode * ) element, tagName,
593 &returnNodeList );
594 }
595 return returnNodeList;
596}
597
598/*================================================================
599* XmlElementGetAttributeNS
600* Retrieves an attribute value by local name and namespace URI.
601* External function.
602*
603* Parameters:
604* namespaceURI: the namespace URI of the attribute to retrieve.
605* localName: the local name of the attribute to retrieve.
606*
607* Return Value:
608* the attr value as a string, or NULL if that attribute does
609* not have the specified value.
610*
611*=================================================================*/
612char *
613XmlElementGetAttributeNS( XmlElement * element,
614 const char * namespaceURI,
615 const char * localName )
616{
617 XmlNode * attrNode;
618
619 if ( ( element == NULL ) || ( namespaceURI == NULL )
620 || ( localName == NULL ) )
621 {
622 return NULL;
623 }
624
625 attrNode = element->node.firstAttr;
626 while ( attrNode != NULL )
627 {
628 if ( strcmp( attrNode->localName, localName ) == 0 && strcmp( attrNode->namespaceURI, namespaceURI ) == 0 ) // found it
629 {
630 return attrNode->nodeValue;
631 }
632 else
633 {
634 attrNode = attrNode->nextSibling;
635 }
636 }
637
638 return NULL;
639
640}
641
642/*================================================================
643* XmlElementSetAttributeNS
644* Adds a new attribute. If an attribute with the same local name
645* and namespace URI is already present on the element, its prefix
646* is changed to be the prefix part of the qualifiedName, and its
647* value is changed to be the value parameter. This value is a
648* simple string.
649* External function.
650*
651* Parameter:
652* namespaceURI: the namespace of the attribute to create or alter.
653* qualifiedName: the qualified name of the attribute to create or alter.
654* value: the value to set in string form.
655*
656* Return Value:
657* XML_OK or failure
658*
659*=================================================================*/
660int
661XmlElementSetAttributeNS(
662 Pool * pool,
663 XmlElement * element,
664 const char * namespaceURI,
665 const char * qualifiedName,
666 const char * value )
667{
668 XmlNode * attrNode = NULL;
669 XmlNode newAttrNode;
670 XmlAttribute *newAttr;
671 int rc;
672
673 if ( ( element == NULL ) || ( namespaceURI == NULL ) ||
674 ( qualifiedName == NULL ) || ( value == NULL ) )
675 {
676 return XML_INVALID_PARAMETER;
677 }
678
679 if ( XmlParserIsValidXmlName( qualifiedName ) == FALSE )
680 {
681 return XML_INVALID_CHARACTER_ERR;
682 }
683
684 XmlNodeInit( &newAttrNode );
685
686 newAttrNode.nodeName = PSTRDUP( qualifiedName );
687 if ( newAttrNode.nodeName == NULL )
688 {
689 return XML_INSUFFICIENT_MEMORY;
690 }
691
692 rc = XmlParserSetNodePrefixAndLocalName(
693#ifdef USE_CWMP_MEMORY_POOL
694 pool ,
695#endif
696
697 &newAttrNode );
698 if ( rc != XML_OK )
699 {
700 XmlParserFreeNodeContent(
701#ifdef USE_CWMP_MEMORY_POOL
702 pool ,
703#endif
704 &newAttrNode );
705 return rc;
706 }
707 // see DOM 2 spec page 59
708 if ( /*( newAttrNode.prefix != NULL && namespaceURI == NULL ) ||*/
709 (newAttrNode.prefix != NULL && strcmp( newAttrNode.prefix, "xml" ) == 0 &&
710 strcmp( namespaceURI,
711 "http://www.w3.org/XML/1998/namespace" ) != 0 )
712 || ( strcmp( qualifiedName, "xmlns" ) == 0
713 && strcmp( namespaceURI,
714 "http://www.w3.org/2000/xmlns/" ) != 0 ) )
715 {
716 XmlParserFreeNodeContent(
717#ifdef USE_CWMP_MEMORY_POOL
718 pool ,
719#endif
720 &newAttrNode );
721 return XML_NAMESPACE_ERR;
722 }
723
724 attrNode = element->node.firstAttr;
725 while ( attrNode != NULL )
726 {
727 if ( strcmp( attrNode->localName, newAttrNode.localName ) == 0 &&
728 strcmp( attrNode->namespaceURI, namespaceURI ) == 0 )
729 {
730 break; //found it
731 }
732 else
733 {
734 attrNode = attrNode->nextSibling;
735 }
736 }
737
738 if ( attrNode != NULL )
739 {
740 if ( attrNode->prefix != NULL )
741 {
742 PFREE( attrNode->prefix ); // remove the old prefix
743 }
744 // replace it with the new prefix
745 attrNode->prefix = PSTRDUP( newAttrNode.prefix );
746 if ( attrNode->prefix == NULL )
747 {
748 XmlParserFreeNodeContent(
749#ifdef USE_CWMP_MEMORY_POOL
750 pool ,
751#endif
752 &newAttrNode );
753 return XML_INSUFFICIENT_MEMORY;
754 }
755
756 if ( attrNode->nodeValue != NULL )
757 {
758 PFREE( attrNode->nodeValue );
759 }
760
761 attrNode->nodeValue = XmlStrduptrim(
762#ifdef USE_CWMP_MEMORY_POOL
763 pool ,
764#endif
765 value );
766 if ( attrNode->nodeValue == NULL )
767 {
768 PFREE( attrNode->prefix );
769 XmlParserFreeNodeContent(
770#ifdef USE_CWMP_MEMORY_POOL
771 pool ,
772#endif
773 &newAttrNode );
774 return XML_INSUFFICIENT_MEMORY;
775 }
776
777 }
778 else
779 {
780 // add a new attribute
781 rc = XmlDocCreateAttributeNSEx(
782#ifdef USE_CWMP_MEMORY_POOL
783 pool ,
784#endif
785
786 ( XmlDocument * )
787 element->node.ownerDocument,
788 namespaceURI, qualifiedName,
789 &newAttr );
790 if ( rc != XML_OK )
791 {
792 return rc;
793 }
794
795 newAttr->node.nodeValue = XmlStrduptrim(
796#ifdef USE_CWMP_MEMORY_POOL
797 pool ,
798#endif
799 value );
800 if ( newAttr->node.nodeValue == NULL )
801 {
802 XmlAttrFree(
803#ifdef USE_CWMP_MEMORY_POOL
804 pool ,
805#endif
806 newAttr );
807 return XML_INSUFFICIENT_MEMORY;
808 }
809
810 if ( XmlElementSetAttributeNodeNS( element, newAttr, NULL ) !=
811 XML_OK )
812 {
813 XmlAttrFree(
814#ifdef USE_CWMP_MEMORY_POOL
815 pool ,
816#endif
817 newAttr );
818 return XML_FAILED;
819 }
820
821 }
822
823 XmlParserFreeNodeContent(
824#ifdef USE_CWMP_MEMORY_POOL
825 pool ,
826#endif
827 &newAttrNode );
828 return XML_OK;
829}
830
831/*================================================================
832* XmlElementRemoveAttributeNS
833* Removes an attribute by local name and namespace URI. The replacing
834* attribute has the same namespace URI and local name, as well as
835* the original prefix.
836* External function.
837*
838* Parameters:
839* namespaceURI: the namespace URI of the attribute to remove.
840* localName: the local name of the atribute to remove.
841*
842* Return Value:
843* XML_OK or failure.
844*
845*=================================================================*/
846int
847XmlElementRemoveAttributeNS(
848 Pool * pool,
849 XmlElement * element,
850 const char * namespaceURI,
851 const char * localName )
852{
853 XmlNode * attrNode;
854
855 if ( ( element == NULL ) || ( namespaceURI == NULL )
856 || ( localName == NULL ) )
857 {
858 return XML_INVALID_PARAMETER;
859 }
860
861 attrNode = element->node.firstAttr;
862 while ( attrNode != NULL )
863 {
864 if ( strcmp( attrNode->localName, localName ) == 0 &&
865 strcmp( attrNode->namespaceURI, namespaceURI ) == 0 )
866 {
867 break; //found it
868 }
869 else
870 {
871 attrNode = attrNode->nextSibling;
872 }
873 }
874
875 if ( attrNode != NULL ) // has the attribute
876 {
877 if ( attrNode->nodeValue != NULL )
878 {
879 PFREE( attrNode->nodeValue );
880 attrNode->nodeValue = NULL;
881 }
882 }
883
884 return XML_OK;
885
886}
887
888/*================================================================
889* XmlElementGetAttributeNodeNS
890* Retrieves an attr node by local name and namespace URI.
891* External function.
892*
893* Parameter:
894* namespaceURI: the namespace of the attribute to retrieve.
895* localName: the local name of the attribute to retrieve.
896*
897* Return Value:
898* The attr node with the specified attribute local name and
899* namespace URI or null if there is no such attribute.
900*
901*=================================================================*/
902XmlAttribute *
903XmlElementGetAttributeNodeNS( XmlElement * element,
904 const char * namespaceURI,
905 const char * localName )
906{
907
908 XmlNode * attrNode;
909
910 if ( ( element == NULL ) || ( namespaceURI == NULL )
911 || ( localName == NULL ) )
912 {
913 return NULL;
914 }
915
916 attrNode = element->node.firstAttr;
917 while ( attrNode != NULL )
918 {
919 if ( strcmp( attrNode->localName, localName ) == 0 && strcmp( attrNode->namespaceURI, namespaceURI ) == 0 ) // found it
920 {
921 break;
922 }
923 else
924 {
925 attrNode = attrNode->nextSibling;
926 }
927 }
928
929 return ( XmlAttribute * ) attrNode;
930
931}
932
933/*================================================================
934* XmlElementSetAttributeNodeNS
935* Adds a new attribute. If an attribute with that local name and
936* that namespace URI is already present in the element, it is replaced
937* by the new one.
938* External function.
939*
940* Parameter:
941* newAttr: the attr node to add to the attribute list.
942*
943* Return Value:
944* If the newAttr attribute replaces an existing attribute with the
945* same local name and namespace, the replaced attr node is returned,
946* otherwise null is returned.
947*
948*=================================================================*/
949int
950XmlElementSetAttributeNodeNS( XmlElement * element,
951 XmlAttribute * newAttr,
952 OUT XmlAttribute ** rtAttr )
953{
954 XmlNode * attrNode;
955 XmlNode * node;
956 XmlNode * prevAttr = NULL;
957 XmlNode * nextAttr = NULL;
958 XmlNode * preSib;
959 XmlNode * nextSib;
960
961 if ( ( element == NULL ) || ( newAttr == NULL ) )
962 {
963 return XML_INVALID_PARAMETER;
964 }
965
966 if ( newAttr->node.ownerDocument != element->node.ownerDocument )
967 {
968 return XML_WRONG_DOCUMENT_ERR;
969 }
970
971 if ( ( newAttr->ownerElement != NULL )
972 && ( newAttr->ownerElement != element ) )
973 {
974 return XML_INUSE_ATTRIBUTE_ERR;
975 }
976
977 newAttr->ownerElement = element;
978 node = ( XmlNode * ) newAttr;
979
980 attrNode = element->node.firstAttr;
981 while ( attrNode != NULL )
982 {
983 if ( strcmp( attrNode->localName, node->localName ) == 0 &&
984 strcmp( attrNode->namespaceURI, node->namespaceURI ) == 0 )
985 {
986 break; //found it
987 }
988 else
989 {
990 attrNode = attrNode->nextSibling;
991 }
992 }
993
994 if ( attrNode != NULL ) // already present, will replace by newAttr
995 {
996 preSib = attrNode->prevSibling;
997 nextSib = attrNode->nextSibling;
998
999 if ( preSib != NULL )
1000 {
1001 preSib->nextSibling = node;
1002 }
1003
1004 if ( nextSib != NULL )
1005 {
1006 nextSib->prevSibling = node;
1007 }
1008
1009 if ( element->node.firstAttr == attrNode )
1010 {
1011 element->node.firstAttr = node;
1012 }
1013
1014 if ( rtAttr != NULL )
1015 {
1016 *rtAttr = ( XmlAttribute * ) attrNode;
1017 }
1018
1019 }
1020 else // add this attribute
1021 {
1022 if ( element->node.firstAttr != NULL ) // element has attribute already
1023 {
1024 prevAttr = element->node.firstAttr;
1025 nextAttr = prevAttr->nextSibling;
1026 while ( nextAttr != NULL )
1027 {
1028 prevAttr = nextAttr;
1029 nextAttr = prevAttr->nextSibling;
1030 }
1031 prevAttr->nextSibling = node;
1032 }
1033 else // this is the first attribute node
1034 {
1035 element->node.firstAttr = node;
1036 node->prevSibling = NULL;
1037 node->nextSibling = NULL;
1038 }
1039
1040 if ( rtAttr != NULL )
1041 {
1042 *rtAttr = NULL;
1043 }
1044 }
1045
1046 return XML_OK;
1047}
1048
1049/*================================================================
1050* XmlElementGetElementsByTagNameNS
1051* Returns a nodeList of all the descendant Elements with a given
1052* local name and namespace in the order in which they are encountered
1053* in a preorder traversal of the element tree.
1054* External function.
1055*
1056* Parameters:
1057* namespaceURI: the namespace URI of the elements to match on. The
1058* special value "*" matches all namespaces.
1059* localName: the local name of the elements to match on. The special
1060* value "*" matches all local names.
1061*
1062* Return Value:
1063* A new nodeList object containing all the matched Elements.
1064*
1065*=================================================================*/
1066XmlNodeList *
1067XmlElementGetElementsByTagNameNS(
1068 Pool * pool,
1069 XmlElement * element,
1070 const char * namespaceURI,
1071 const char * localName )
1072{
1073 XmlNode * node = ( XmlNode * ) element;
1074 XmlNodeList *nodeList = NULL;
1075
1076 if ( ( element != NULL ) && ( namespaceURI != NULL )
1077 && ( localName != NULL ) )
1078 {
1079 XmlNodeGetElementsByTagNameNS(
1080#ifdef USE_CWMP_MEMORY_POOL
1081 pool ,
1082#endif
1083
1084 node, namespaceURI, localName,
1085 &nodeList );
1086 }
1087
1088 return nodeList;
1089}
1090
1091/*================================================================
1092* XmlElementHasAttribute
1093* Returns true when an attribute with a given name is specified on
1094* this element, false otherwise.
1095* External function.
1096*
1097* Parameters:
1098* name: the name of the attribute to look for.
1099*
1100* Return Value:
1101* ture if an attribute with the given name is specified on this
1102* element, false otherwise.
1103*
1104*=================================================================*/
1105BOOL
1106XmlElementHasAttribute( XmlElement * element,
1107 const char * name )
1108{
1109
1110 XmlNode * attrNode;
1111
1112 if ( ( element == NULL ) || ( name == NULL ) )
1113 {
1114 return FALSE;
1115 }
1116
1117 attrNode = element->node.firstAttr;
1118 while ( attrNode != NULL )
1119 {
1120 if ( strcmp( attrNode->nodeName, name ) == 0 )
1121 {
1122 return TRUE;
1123 }
1124 else
1125 {
1126 attrNode = attrNode->nextSibling;
1127 }
1128 }
1129
1130 return FALSE;
1131}
1132
1133/*================================================================
1134* XmlElementHasAttributeNS
1135* Returns true when attribute with a given local name and namespace
1136* URI is specified on this element, false otherwise.
1137* External function.
1138*
1139* Parameters:
1140* namespaceURI: the namespace URI of the attribute to look for.
1141* localName: the local name of the attribute to look for.
1142*
1143* Return Value:
1144* true if an attribute with the given local name and namespace URI
1145* is specified, false otherwise.
1146*
1147*=================================================================*/
1148BOOL
1149XmlElementHasAttributeNS( XmlElement * element,
1150 const char * namespaceURI,
1151 const char * localName )
1152{
1153
1154 XmlNode * attrNode;
1155
1156 if ( ( element == NULL ) || ( namespaceURI == NULL )
1157 || ( localName == NULL ) )
1158 {
1159 return FALSE;
1160 }
1161
1162 attrNode = element->node.firstAttr;
1163 while ( attrNode != NULL )
1164 {
1165 if ( strcmp( attrNode->localName, localName ) == 0 &&
1166 strcmp( attrNode->namespaceURI, namespaceURI ) == 0 )
1167 {
1168 return TRUE;
1169 }
1170 else
1171 {
1172 attrNode = attrNode->nextSibling;
1173 }
1174 }
1175
1176 return FALSE;
1177}
1178
1179
1180/*================================================================
1181* XmlElementFree
1182* XFREEs a element node.
1183* External function.
1184*
1185*=================================================================*/
1186void
1187XmlElementFree(
1188 Pool * pool,
1189 XmlElement * element )
1190{
1191 if ( element != NULL )
1192 {
1193 XmlNodeFree(
1194#ifdef USE_CWMP_MEMORY_POOL
1195 pool ,
1196#endif
1197 ( XmlNode * ) element );
1198 }
1199}