Coverage Report

Created: 2026-11-12 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pupnp/ixml/src/element.c
Line
Count
Source
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
 * \file
35
 */
36
37
#include "ixml.h"
38
#include "ixmlparser.h"
39
40
#include <stdlib.h> /* for free() */
41
#include <string.h>
42
43
#include "posix_overwrites.h" // IWYU pragma: keep
44
45
typedef struct s_extra_parameters
46
{
47
  const void *p1;
48
  const void *p2;
49
} Extra_Parameters_t;
50
51
typedef int (*Find_Condition_t)(
52
  const IXML_Node *n, const Extra_Parameters_t *p);
53
54
void ixmlElement_init(IXML_Element *element)
55
0
{
56
0
  if (element) {
57
0
    memset(element, 0, sizeof(IXML_Element));
58
0
  }
59
0
}
60
61
const DOMString ixmlElement_getTagName(IXML_Element *element)
62
0
{
63
0
  if (element) {
64
0
    return element->tagName;
65
0
  } else {
66
0
    return NULL;
67
0
  }
68
0
}
69
70
int ixmlElement_setTagName(IXML_Element *element, const char *tagName)
71
0
{
72
0
  int rc = IXML_SUCCESS;
73
74
0
  if (!element || !tagName) {
75
0
    return IXML_FAILED;
76
0
  }
77
78
0
  if (element->tagName) {
79
0
    free(element->tagName);
80
0
  }
81
0
  element->tagName = strdup(tagName);
82
0
  if (!element->tagName) {
83
0
    rc = IXML_INSUFFICIENT_MEMORY;
84
0
  }
85
86
0
  return rc;
87
0
}
88
89
static int find_condition_name(const IXML_Node *n, const Extra_Parameters_t *p)
90
0
{
91
0
  const DOMString name;
92
0
  int ret;
93
94
0
  name = (const DOMString)p->p1;
95
0
  ret = n->nodeName && //
96
0
        strcmp(n->nodeName, name) == 0;
97
98
0
  return ret;
99
0
}
100
101
static IXML_Node *get_attribute_node( //
102
  Find_Condition_t condition,
103
  IXML_Element *element,
104
  Extra_Parameters_t *p)
105
0
{
106
0
  IXML_Node *n = element->n.firstAttr;
107
108
0
  while (n) {
109
0
    if (condition(n, p)) {
110
0
      return n;
111
0
    }
112
0
    n = n->nextSibling;
113
0
  }
114
115
0
  return NULL;
116
0
}
117
118
const DOMString ixmlElement_getAttribute(
119
  IXML_Element *element, const DOMString name)
120
0
{
121
0
  IXML_Node *attrNode;
122
0
  Extra_Parameters_t p;
123
124
0
  if (!element || !name) {
125
0
    return NULL;
126
0
  }
127
0
  p.p1 = name;
128
0
  p.p2 = NULL;
129
0
  attrNode = get_attribute_node(find_condition_name, element, &p);
130
0
  if (attrNode) {
131
0
    return attrNode->nodeValue;
132
0
  }
133
134
0
  return NULL;
135
0
}
136
137
int ixmlElement_setAttribute( //
138
  IXML_Element *element,
139
  const DOMString name,
140
  const DOMString value)
141
0
{
142
0
  int error_code = IXML_SUCCESS;
143
0
  IXML_Node *attrNode = NULL;
144
0
  Extra_Parameters_t p;
145
146
0
  if (!element || !name || !value) {
147
0
    return IXML_INVALID_PARAMETER;
148
0
  }
149
0
  if (Parser_isValidXmlName(name) == 0) {
150
0
    return IXML_INVALID_CHARACTER_ERR;
151
0
  }
152
0
  p.p1 = name;
153
0
  p.p2 = NULL;
154
0
  attrNode = get_attribute_node(find_condition_name, element, &p);
155
0
  if (attrNode) {
156
0
    if (attrNode->nodeValue) {
157
      /* Attribute name has a value already */
158
0
      free(attrNode->nodeValue);
159
0
    }
160
0
    attrNode->nodeValue = strdup(value);
161
0
    if (!attrNode->nodeValue) {
162
0
      error_code = IXML_INSUFFICIENT_MEMORY;
163
0
      goto ErrorHandler;
164
0
    }
165
0
  } else {
166
    /* attrNode was not found */
167
0
    IXML_Attr *newAttr;
168
169
    /* Add a new attribute */
170
0
    error_code = ixmlDocument_createAttributeEx(
171
0
      (IXML_Document *)element->n.ownerDocument,
172
0
      name,
173
0
      &newAttr);
174
0
    if (error_code != IXML_SUCCESS) {
175
0
      goto ErrorHandler;
176
0
    }
177
0
    newAttr->n.nodeValue = strdup(value);
178
0
    if (!newAttr->n.nodeValue) {
179
0
      ixmlAttr_free(newAttr);
180
0
      error_code = IXML_INSUFFICIENT_MEMORY;
181
0
      goto ErrorHandler;
182
0
    }
183
0
    error_code = ixmlElement_setAttributeNode( //
184
0
      element,
185
0
      newAttr,
186
0
      NULL);
187
0
    if (error_code != IXML_SUCCESS) {
188
0
      ixmlAttr_free(newAttr);
189
0
      goto ErrorHandler;
190
0
    }
191
0
  }
192
193
0
ErrorHandler:
194
0
  return error_code;
195
0
}
196
197
int ixmlElement_removeAttribute(IXML_Element *element, const DOMString name)
198
0
{
199
0
  IXML_Node *attrNode;
200
0
  Extra_Parameters_t p;
201
202
0
  if (!element || !name) {
203
0
    return IXML_INVALID_PARAMETER;
204
0
  }
205
0
  p.p1 = name;
206
0
  p.p2 = NULL;
207
0
  attrNode = get_attribute_node(find_condition_name, element, &p);
208
0
  if (attrNode && attrNode->nodeValue) {
209
    /* Has the attribute */
210
0
    free(attrNode->nodeValue);
211
0
    attrNode->nodeValue = NULL;
212
0
  }
213
214
0
  return IXML_SUCCESS;
215
0
}
216
217
IXML_Attr *ixmlElement_getAttributeNode(
218
  IXML_Element *element, const DOMString name)
219
0
{
220
0
  Extra_Parameters_t p;
221
222
0
  if (!element || !name) {
223
0
    return NULL;
224
0
  }
225
0
  p.p1 = name;
226
0
  p.p2 = NULL;
227
0
  return (IXML_Attr *)get_attribute_node(
228
0
    find_condition_name, element, &p);
229
0
}
230
231
static int ixmlElement_setAttributeNode_common(
232
  /* IN */ Find_Condition_t find_condition,
233
  /* IN */ IXML_Element *element,
234
  /* IN */ IXML_Attr *newAttr,
235
  /* OUT */ IXML_Attr **rtAttr)
236
0
{
237
0
  IXML_Node *node = NULL;
238
0
  IXML_Node *attrNode = NULL;
239
0
  Extra_Parameters_t p;
240
241
0
  if (!element || !newAttr) {
242
0
    return IXML_INVALID_PARAMETER;
243
0
  }
244
0
  if (newAttr->n.ownerDocument != element->n.ownerDocument) {
245
0
    return IXML_WRONG_DOCUMENT_ERR;
246
0
  }
247
0
  if (newAttr->ownerElement && newAttr->ownerElement != element) {
248
0
    return IXML_INUSE_ATTRIBUTE_ERR;
249
0
  }
250
0
  newAttr->ownerElement = element;
251
0
  node = &newAttr->n;
252
0
  for (attrNode = element->n.firstAttr; attrNode;
253
0
    attrNode = attrNode->nextSibling) {
254
0
    if (attrNode == node) {
255
      /* newAttr is already an attribute of element: nothing
256
       * to do, and nothing was replaced. The search below
257
       * cannot tell, it may find another attribute or none.
258
       */
259
0
      if (rtAttr) {
260
0
        *rtAttr = NULL;
261
0
      }
262
0
      return IXML_SUCCESS;
263
0
    }
264
0
  }
265
0
  p.p1 = node;
266
0
  p.p2 = NULL;
267
0
  attrNode = get_attribute_node(find_condition, element, &p);
268
0
  if (attrNode) {
269
    /* Already present, will be replaced by newAttr */
270
0
    IXML_Node *prevSib = attrNode->prevSibling;
271
0
    IXML_Node *nextSib = attrNode->nextSibling;
272
273
0
    node->prevSibling = prevSib;
274
0
    node->nextSibling = nextSib;
275
0
    if (prevSib) {
276
0
      prevSib->nextSibling = node;
277
0
    }
278
0
    if (nextSib) {
279
0
      nextSib->prevSibling = node;
280
0
    }
281
0
    if (element->n.firstAttr == attrNode) {
282
0
      element->n.firstAttr = node;
283
0
    }
284
0
    node->parentNode = attrNode->parentNode;
285
0
    node->firstChild = attrNode->firstChild; // Should be NULL
286
0
    node->firstAttr = attrNode->firstAttr;   // Should be NULL
287
0
    attrNode->parentNode = NULL;
288
0
    attrNode->prevSibling = NULL;
289
0
    attrNode->nextSibling = NULL;
290
0
    attrNode->firstChild = NULL;
291
0
    attrNode->firstAttr = NULL;
292
0
    ((IXML_Attr *)attrNode)->ownerElement = NULL;
293
0
    if (rtAttr) {
294
0
      *rtAttr = (IXML_Attr *)attrNode;
295
0
    } else {
296
0
      ixmlAttr_free((IXML_Attr *)attrNode);
297
0
    }
298
0
  } else {
299
    /* Add this attribute */
300
0
    if (element->n.firstAttr) {
301
      /* Element already has an attribute, go to the end */
302
0
      IXML_Node *prevAttr = element->n.firstAttr;
303
0
      IXML_Node *nextAttr = prevAttr->nextSibling;
304
0
      while (nextAttr) {
305
0
        prevAttr = nextAttr;
306
0
        nextAttr = prevAttr->nextSibling;
307
0
      }
308
0
      prevAttr->nextSibling = node;
309
0
      node->prevSibling = prevAttr;
310
0
      node->parentNode = &element->n;
311
0
    } else {
312
      /* This is the first attribute node */
313
0
      element->n.firstAttr = node;
314
0
      node->prevSibling = NULL;
315
0
      node->nextSibling = NULL;
316
0
      node->parentNode = &element->n;
317
0
    }
318
0
    if (rtAttr) {
319
0
      *rtAttr = NULL;
320
0
    }
321
0
  }
322
323
0
  return IXML_SUCCESS;
324
0
}
325
326
static int find_condition_node_name(
327
  const IXML_Node *n1, const Extra_Parameters_t *p)
328
0
{
329
0
  const IXML_Node *n2 = (const IXML_Node *)p->p1;
330
0
  int ret;
331
332
0
  ret = n1->nodeName && //
333
0
        n2->nodeName && //
334
0
        !strcmp(n1->nodeName, n2->nodeName);
335
336
0
  return ret;
337
0
}
338
339
int ixmlElement_setAttributeNode(
340
  /* IN */ IXML_Element *element,
341
  /* IN */ IXML_Attr *newAttr,
342
  /* OUT */ IXML_Attr **rtAttr)
343
0
{
344
0
  return ixmlElement_setAttributeNode_common(
345
0
    find_condition_node_name, element, newAttr, rtAttr);
346
0
}
347
348
static int find_condition_node(const IXML_Node *n1, const Extra_Parameters_t *p)
349
0
{
350
0
  const IXML_Node *n2 = (const IXML_Node *)p->p1;
351
352
0
  return ixmlNode_compare(n1, n2);
353
0
}
354
355
int ixmlElement_removeAttributeNode(
356
  IXML_Element *element, IXML_Attr *oldAttr, IXML_Attr **rtAttr)
357
0
{
358
0
  IXML_Node *attrNode;
359
0
  Extra_Parameters_t p;
360
361
0
  if (!element || !oldAttr || !rtAttr) {
362
0
    return IXML_INVALID_PARAMETER;
363
0
  }
364
0
  p.p1 = oldAttr;
365
0
  p.p2 = NULL;
366
0
  attrNode = get_attribute_node(find_condition_node, element, &p);
367
0
  if (attrNode) {
368
    /* Has the attribute */
369
0
    IXML_Node *prevSib = attrNode->prevSibling;
370
0
    IXML_Node *nextSib = attrNode->nextSibling;
371
0
    if (prevSib) {
372
0
      prevSib->nextSibling = nextSib;
373
0
    }
374
0
    if (nextSib) {
375
0
      nextSib->prevSibling = prevSib;
376
0
    }
377
0
    if (element->n.firstAttr == attrNode) {
378
0
      element->n.firstAttr = nextSib;
379
0
    }
380
0
    attrNode->parentNode = NULL;
381
0
    attrNode->prevSibling = NULL;
382
0
    attrNode->nextSibling = NULL;
383
0
    ((IXML_Attr *)attrNode)->ownerElement = NULL;
384
0
    *rtAttr = (IXML_Attr *)attrNode;
385
0
    return IXML_SUCCESS;
386
0
  } else {
387
0
    return IXML_NOT_FOUND_ERR;
388
0
  }
389
0
}
390
391
IXML_NodeList *ixmlElement_getElementsByTagName(
392
  IXML_Element *element, const DOMString tagName)
393
0
{
394
0
  IXML_NodeList *returnNodeList = NULL;
395
396
0
  if (element && tagName) {
397
0
    ixmlNode_getElementsByTagName(
398
0
      (IXML_Node *)element, tagName, &returnNodeList);
399
0
  }
400
401
0
  return returnNodeList;
402
0
}
403
404
static int find_condition_ns_ln(const IXML_Node *n, const Extra_Parameters_t *p)
405
0
{
406
0
  const DOMString namespaceURI = (const DOMString)p->p1;
407
0
  const DOMString localName = (const DOMString)p->p2;
408
0
  int ret;
409
410
0
  ret = n->localName &&           //
411
0
        n->namespaceURI &&         //
412
0
        strcmp(n->localName, localName) == 0 && //
413
0
        strcmp(n->namespaceURI, namespaceURI) == 0;
414
415
0
  return ret;
416
0
}
417
418
const DOMString ixmlElement_getAttributeNS(
419
  /* IN */ IXML_Element *element,
420
  /* IN */ const DOMString namespaceURI,
421
  /* IN */ const DOMString localName)
422
0
{
423
0
  IXML_Node *n;
424
0
  Extra_Parameters_t p;
425
426
0
  if (!element || !namespaceURI || !localName) {
427
0
    return NULL;
428
0
  }
429
0
  p.p1 = namespaceURI;
430
0
  p.p2 = localName;
431
0
  n = get_attribute_node(find_condition_ns_ln, element, &p);
432
0
  if (n) {
433
0
    return n->nodeValue;
434
0
  }
435
436
0
  return NULL;
437
0
}
438
439
static int check_namespace_error(IXML_Node *n,
440
  const DOMString namespaceURI,
441
  const DOMString qualifiedName)
442
0
{
443
  /* see DOM 2 spec page 59 */
444
  /* clang-format off */
445
0
  return //
446
0
    (n->prefix &&
447
0
     !namespaceURI)
448
0
    ||
449
0
    (n->prefix &&
450
0
     strcmp(n->prefix, "xml") == 0 &&
451
0
     strcmp(namespaceURI, "http://www.w3.org/XML/1998/namespace") != 0)
452
0
    ||
453
0
    (strcmp(qualifiedName, "xmlns") == 0 &&
454
0
     strcmp(namespaceURI, "http://www.w3.org/2000/xmlns/") != 0);
455
  /* clang-format on */
456
0
}
457
458
int ixmlElement_setAttributeNS( //
459
  IXML_Element *element,
460
  const DOMString namespaceURI,
461
  const DOMString qualifiedName,
462
  const DOMString value)
463
0
{
464
0
  int error_code = IXML_SUCCESS;
465
0
  IXML_Node *attrNode = NULL;
466
0
  IXML_Node newAttrNode;
467
0
  int namespace_error;
468
0
  Extra_Parameters_t p;
469
470
0
  if (!element || !namespaceURI || !qualifiedName || !value) {
471
0
    return IXML_INVALID_PARAMETER;
472
0
  }
473
0
  if (Parser_isValidXmlName(qualifiedName) == 0) {
474
0
    return IXML_INVALID_CHARACTER_ERR;
475
0
  }
476
0
  ixmlNode_init(&newAttrNode);
477
0
  newAttrNode.nodeName = strdup(qualifiedName);
478
0
  if (!newAttrNode.nodeName) {
479
0
    return IXML_INSUFFICIENT_MEMORY;
480
0
  }
481
0
  error_code = Parser_setNodePrefixAndLocalName(&newAttrNode);
482
0
  if (error_code != IXML_SUCCESS) {
483
0
    goto ErrorHandler;
484
0
  }
485
0
  namespace_error = check_namespace_error(
486
0
    &newAttrNode, namespaceURI, qualifiedName);
487
0
  if (namespace_error) {
488
0
    error_code = IXML_NAMESPACE_ERR;
489
0
    goto ErrorHandler;
490
0
  }
491
0
  p.p1 = namespaceURI;
492
0
  p.p2 = newAttrNode.localName;
493
0
  attrNode = get_attribute_node(find_condition_ns_ln, element, &p);
494
0
  if (attrNode) {
495
    /* Copy the value first, so that a failure leaves the
496
     * attribute as it was. */
497
0
    char *newValue = strdup(value);
498
499
0
    if (!newValue) {
500
0
      error_code = IXML_INSUFFICIENT_MEMORY;
501
0
      goto ErrorHandler;
502
0
    }
503
0
    if (attrNode->prefix) {
504
      /* Remove the old prefix */
505
0
      free(attrNode->prefix);
506
0
    }
507
    /* replace it with the new prefix */
508
0
    attrNode->prefix = newAttrNode.prefix;
509
0
    newAttrNode.prefix = NULL;
510
0
    if (attrNode->nodeValue) {
511
      /* Attribute name has a value already */
512
0
      free(attrNode->nodeValue);
513
0
    }
514
0
    attrNode->nodeValue = newValue;
515
0
  } else {
516
    /* attrNode was not found */
517
0
    IXML_Attr *newAttr;
518
519
    /* Add a new attribute */
520
0
    error_code = ixmlDocument_createAttributeNSEx(
521
0
      (IXML_Document *)element->n.ownerDocument,
522
0
      namespaceURI,
523
0
      qualifiedName,
524
0
      &newAttr);
525
0
    if (error_code != IXML_SUCCESS) {
526
0
      goto ErrorHandler;
527
0
    }
528
0
    newAttr->n.nodeValue = strdup(value);
529
0
    if (!newAttr->n.nodeValue) {
530
0
      ixmlAttr_free(newAttr);
531
0
      error_code = IXML_INSUFFICIENT_MEMORY;
532
0
      goto ErrorHandler;
533
0
    }
534
0
    error_code = ixmlElement_setAttributeNodeNS( //
535
0
      element,
536
0
      newAttr,
537
0
      NULL);
538
0
    if (error_code != IXML_SUCCESS) {
539
0
      ixmlAttr_free(newAttr);
540
0
      goto ErrorHandler;
541
0
    }
542
0
  }
543
544
0
ErrorHandler:
545
0
  Parser_freeNodeContent(&newAttrNode);
546
547
0
  return error_code;
548
0
}
549
550
int ixmlElement_removeAttributeNS(IXML_Element *element,
551
  const DOMString namespaceURI,
552
  const DOMString localName)
553
0
{
554
0
  IXML_Node *attrNode = NULL;
555
556
0
  if (!element || !namespaceURI || !localName) {
557
0
    return IXML_INVALID_PARAMETER;
558
0
  }
559
560
0
  attrNode = element->n.firstAttr;
561
0
  while (attrNode) {
562
0
    if (attrNode->localName && attrNode->namespaceURI &&
563
0
      strcmp(attrNode->localName, localName) == 0 &&
564
0
      strcmp(attrNode->namespaceURI, namespaceURI) == 0) {
565
      /* Found it */
566
0
      break;
567
0
    }
568
0
    attrNode = attrNode->nextSibling;
569
0
  }
570
0
  if (attrNode) {
571
    /* Has the attribute */
572
0
    if (attrNode->nodeValue) {
573
0
      free(attrNode->nodeValue);
574
0
      attrNode->nodeValue = NULL;
575
0
    }
576
0
  }
577
578
0
  return IXML_SUCCESS;
579
0
}
580
581
IXML_Attr *ixmlElement_getAttributeNodeNS(IXML_Element *element,
582
  const DOMString namespaceURI,
583
  const DOMString localName)
584
0
{
585
0
  Extra_Parameters_t p;
586
587
0
  if (!element || !namespaceURI || !localName) {
588
0
    return NULL;
589
0
  }
590
0
  p.p1 = namespaceURI;
591
0
  p.p2 = localName;
592
0
  return (IXML_Attr *)get_attribute_node(
593
0
    find_condition_ns_ln, element, &p);
594
0
}
595
596
static int find_condition_node_ns_ln(
597
  const IXML_Node *n1, const Extra_Parameters_t *p)
598
0
{
599
0
  const IXML_Node *n2 = (const IXML_Node *)p->p1;
600
0
  int ret;
601
602
0
  ret = n1->localName &&            //
603
0
        n1->namespaceURI &&          //
604
0
        n2->localName &&            //
605
0
        n2->namespaceURI &&          //
606
0
        !strcmp(n1->localName, n2->localName) && //
607
0
        !strcmp(n1->namespaceURI, n2->namespaceURI);
608
609
0
  return ret;
610
0
}
611
612
int ixmlElement_setAttributeNodeNS(
613
  /* IN */ IXML_Element *element,
614
  /* IN */ IXML_Attr *newAttr,
615
  /* OUT */ IXML_Attr **rtAttr)
616
0
{
617
0
  return ixmlElement_setAttributeNode_common(
618
0
    find_condition_node_ns_ln, element, newAttr, rtAttr);
619
0
}
620
621
IXML_NodeList *ixmlElement_getElementsByTagNameNS(IXML_Element *element,
622
  const DOMString namespaceURI,
623
  const DOMString localName)
624
0
{
625
0
  IXML_Node *node = (IXML_Node *)element;
626
0
  IXML_NodeList *nodeList = NULL;
627
628
0
  if (element && namespaceURI && localName) {
629
0
    ixmlNode_getElementsByTagNameNS(
630
0
      node, namespaceURI, localName, &nodeList);
631
0
  }
632
633
0
  return nodeList;
634
0
}
635
636
int ixmlElement_hasAttribute(IXML_Element *element, const DOMString name)
637
0
{
638
0
  IXML_Node *attrNode = NULL;
639
640
0
  if (!element || !name) {
641
0
    return 0;
642
0
  }
643
644
0
  attrNode = element->n.firstAttr;
645
0
  while (attrNode) {
646
0
    if (attrNode->nodeName &&
647
0
      strcmp(attrNode->nodeName, name) == 0) {
648
0
      return 1;
649
0
    }
650
0
    attrNode = attrNode->nextSibling;
651
0
  }
652
653
0
  return 0;
654
0
}
655
656
int ixmlElement_hasAttributeNS(IXML_Element *element,
657
  const DOMString namespaceURI,
658
  const DOMString localName)
659
0
{
660
0
  IXML_Node *attrNode = NULL;
661
662
0
  if (!element || !namespaceURI || !localName) {
663
0
    return 0;
664
0
  }
665
666
0
  attrNode = element->n.firstAttr;
667
0
  while (attrNode) {
668
0
    if (attrNode->localName && attrNode->namespaceURI &&
669
0
      strcmp(attrNode->localName, localName) == 0 &&
670
0
      strcmp(attrNode->namespaceURI, namespaceURI) == 0) {
671
0
      return 1;
672
0
    }
673
0
    attrNode = attrNode->nextSibling;
674
0
  }
675
676
0
  return 0;
677
0
}
678
679
void ixmlElement_free(IXML_Element *element)
680
0
{
681
0
  if (element) {
682
0
    ixmlNode_free((IXML_Node *)element);
683
0
  }
684
0
}