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