Coverage Report

Created: 2025-12-03 06:25

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