/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 | } |