1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
2 /* gdome-xml-node.c
3 *
4 * Copyright (C) 1999 Raph Levien <raph@acm.org>
5 * Copyright (C) 2000 Mathieu Lacage <mathieu@gnu.org>
6 * Copyright (C) 2000 Anders Carlsson <andersca@gnu.org>
7 * Copyright (C) 2001 Paolo Casarini <paolo@casarini.org>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27 #include <sys/time.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include "gdome.h"
32 #include "gdome-events.h"
33 #include "gdome-refdebug.h"
34 #include "gdome-treegc.h"
35 #include <libxml/tree.h>
36 #include <libxml/parser.h>
37 #include <libxml/xmlmemory.h>
38 #include <libxml/hash.h>
39 #include "gdome-xml-util.h"
40 #include "gdome-xml-xmlmemory.h"
41 #include "gdome-xml-xmlutil.h"
42 #include "gdome-xml-xmldtdutil.h"
43 #include "gdome-xml-str.h"
44 #include "gdome-evt-event.h"
45 #include "gdome-evt-eventl.h"
46 #include "gdome-evt-mevent.h"
47 #include "gdome-evt-propagation.h"
48 #include "gdome-xml-nodel.h"
49 #include "gdome-xml-node.h"
50 #include "gdome-xml-document.h"
51 #include "gdome-xml-element.h"
52 #include "gdome-xml-attribute.h"
53 #include "gdome-xml-cdata.h"
54 #include "gdome-xml-entityref.h"
55 #include "gdome-xml-text.h"
56 #include "gdome-xml-cdatas.h"
57 #include "gdome-xml-comment.h"
58 #include "gdome-xml-entity.h"
59 #include "gdome-xml-pi.h"
60 #include "gdome-xml-notation.h"
61 #include "gdome-xml-documentt.h"
62 #include "gdome-xml-documentf.h"
63 #include "gdome-xml-domimpl.h"
64 #include "gdome-xpath.h"
65 #include "gdome-xml-xpns.h"
66
67 /* indexed by node type
68 first one is NULL because there
69 is no node type number 0
70 cf: spec p25 (DOM 1). interface Node.
71 */
72 const void * gdome_xml_vtabs[] = {
73 NULL,
74 &gdome_xml_el_vtab,
75 &gdome_xml_a_vtab,
76 &gdome_xml_t_vtab,
77 &gdome_xml_cds_vtab,
78 &gdome_xml_er_vtab,
79 &gdome_xml_ent_vtab,
80 &gdome_xml_pi_vtab,
81 &gdome_xml_c_vtab,
82 &gdome_xml_doc_vtab,
83 &gdome_xml_dt_vtab,
84 &gdome_xml_df_vtab,
85 &gdome_xml_not_vtab,
86 &gdome_xml_doc_vtab,
87 &gdome_xml_dt_vtab,
88 NULL,
89 NULL,
90 &gdome_xml_ent_vtab
91 };
92
93 /***************
94 * Virtual Table
95 **************/
96 const GdomeNodeVtab gdome_xml_n_vtab =
97 {
98 gdome_xml_n_ref,
99 gdome_xml_n_unref,
100 gdome_xml_n_query_interface,
101 gdome_xml_n_nodeName,
102 gdome_xml_n_nodeValue,
103 gdome_xml_n_set_nodeValue,
104 gdome_xml_n_nodeType,
105 gdome_xml_n_parentNode,
106 gdome_xml_n_childNodes,
107 gdome_xml_n_firstChild,
108 gdome_xml_n_lastChild,
109 gdome_xml_n_previousSibling,
110 gdome_xml_n_nextSibling,
111 gdome_xml_n_attributes,
112 gdome_xml_n_ownerDocument,
113 gdome_xml_n_insertBefore,
114 gdome_xml_n_replaceChild,
115 gdome_xml_n_removeChild,
116 gdome_xml_n_appendChild,
117 gdome_xml_n_hasChildNodes,
118 gdome_xml_n_cloneNode,
119 gdome_xml_n_normalize,
120 gdome_xml_n_isSupported,
121 gdome_xml_n_namespaceURI,
122 gdome_xml_n_prefix,
123 gdome_xml_n_set_prefix,
124 gdome_xml_n_localName,
125 gdome_xml_n_hasAttributes,
126 gdome_xml_n_addEventListener,
127 gdome_xml_n_removeEventListener,
128 gdome_xml_n_dispatchEvent,
129 gdome_xml_n_subTreeDispatchEvent,
130 gdome_xml_n_canAppend
131 };
132
133
134 /* function to get the xmlNode from a GdomeNode */
135 xmlNode *
gdome_xml_n_get_xmlNode(GdomeNode * node)136 gdome_xml_n_get_xmlNode (GdomeNode *node)
137 {
138 Gdome_xml_Node *xmlnode;
139
140 xmlnode = (Gdome_xml_Node *)node;
141
142 return xmlnode->n;
143 }
144
145 /***********************************************************
146 ***** Constructor and Reference Count Implementation ******
147 ***********************************************************/
148
149 /**
150 * gdome_xml_n_mkref:
151 * @n: The libxml node of which a Gdome reference is wanted
152 *
153 * Constructor of the Node structure.
154 * Returns: the reference to the Gdome node wanted.
155 */
156 GdomeNode *
gdome_xml_n_mkref(xmlNode * n)157 gdome_xml_n_mkref (xmlNode *n) {
158 Gdome_xml_Node *result = NULL;
159 xmlElementType type;
160
161 if (n == NULL)
162 return NULL;
163
164 type = n->type;
165 if (n->_private && type != XML_NAMESPACE_DECL) {
166 result = (Gdome_xml_Node *)n->_private;
167 result->refcnt++;
168 } else {
169 switch (type) {
170 case XML_ELEMENT_NODE:
171 case XML_TEXT_NODE:
172 case XML_CDATA_SECTION_NODE:
173 case XML_ENTITY_REF_NODE:
174 case XML_PI_NODE:
175 case XML_COMMENT_NODE:
176 case XML_NOTATION_NODE:
177 case XML_DOCUMENT_FRAG_NODE:
178 case XML_ATTRIBUTE_NODE:
179 case XML_ENTITY_DECL: /*libxml use this instead of XML_ENTITY_NODE*/
180 result = g_new (Gdome_xml_Node, 1);
181
182 result->refcnt = 1;
183 result->vtab = (GdomeNodeVtab *)gdome_xml_vtabs[n->type];
184 result->super.user_data = NULL;
185 result->n = n;
186 if (type == XML_NOTATION_NODE || type == XML_ENTITY_NODE || type == XML_ENTITY_DECL)
187 result->accessType = GDOME_READONLY_NODE;
188 else
189 result->accessType = GDOME_READWRITE_NODE;
190 result->ll = NULL;
191
192 n->_private = result;
193
194 #ifdef DEBUG_REFCNT
195 gdome_refdbg_addRef ((void *)result, GDOME_REFDBG_NODE);
196 #endif
197 gdome_treegc_addNode ((GdomeNode *)result);
198
199 break;
200 case XML_DOCUMENT_TYPE_NODE:
201 case XML_DTD_NODE:
202 return (GdomeNode *)gdome_xml_dt_mkref ((xmlDtd *)n);
203 case XML_HTML_DOCUMENT_NODE:
204 case XML_DOCUMENT_NODE:
205 return (GdomeNode *)gdome_xml_doc_mkref ((xmlDoc *)n);
206 case XML_NAMESPACE_DECL:
207 return (GdomeNode *)gdome_xml_xpns_mkref ((xmlNs *)n);
208 default:
209 g_warning ("gdome_xml_n_mkref: invalid node type");
210 break;
211 }
212 }
213 return (GdomeNode *)result;
214 }
215
216 /**
217 * gdome_xml_n_ref:
218 * @self: Node Object ref
219 * @exc: Exception Object ref
220 *
221 * Increase the reference count of the specified Node.
222 */
223 void
gdome_xml_n_ref(GdomeNode * self,GdomeException * exc)224 gdome_xml_n_ref (GdomeNode *self, GdomeException *exc) {
225 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
226
227 g_return_if_fail (priv != NULL);
228 g_return_if_fail (GDOME_XML_IS_N (priv));
229 g_return_if_fail (exc != NULL);
230
231 priv->refcnt++;
232 }
233
234 /**
235 * gdome_xml_n_unref:
236 * @self: Node Object ref
237 * @exc: Exception Object ref
238 *
239 * Decrease the reference count of the specified Node. Free the Node structure
240 * if the Node will have zero reference.
241 */
242 void
gdome_xml_n_unref(GdomeNode * self,GdomeException * exc)243 gdome_xml_n_unref (GdomeNode *self, GdomeException *exc) {
244 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
245 xmlElementType type;
246
247 g_return_if_fail (priv != NULL);
248 g_return_if_fail (GDOME_XML_IS_N (priv));
249 g_return_if_fail (exc != NULL);
250
251 type = gdome_xmlGetType (priv->n);
252 switch (type) {
253 case XML_DOCUMENT_TYPE_NODE:
254 case XML_DTD_NODE:
255 return gdome_xml_dt_unref (self, exc);
256 case XML_DOCUMENT_NODE:
257 return gdome_xml_doc_unref (self, exc);
258 default:
259 if (priv->refcnt > 0)
260 priv->refcnt--;
261
262 if (priv->refcnt == 0 && priv->ll == NULL) {
263 xmlNode *n = (xmlNode *)priv->n;
264
265 gdome_treegc_delNode (self);
266
267 n->_private = NULL;
268 if (type != XML_NOTATION_NODE &&
269 type != XML_ENTITY_DECL &&
270 n->parent == NULL)
271 gdome_xmlFreeSubtree (n);
272 else {
273 if (type == XML_ATTRIBUTE_NODE)
274 if (gdome_xmlIsNsDecl ((xmlAttr *)n))
275 gdome_xmlFreeSubtree (n);
276 }
277
278 #ifdef DEBUG_REFCNT
279 gdome_refdbg_delRef ((void *)self, GDOME_REFDBG_NODE);
280 #endif
281 g_free (self);
282 }
283 }
284 }
285
286 /**
287 * gdome_xml_n_query_interface:
288 * @self: Node Object ref
289 * @interface: interface needed
290 * @exc: Exception Object ref
291 *
292 * Returns: a reference to this object that implements the @interface needed,
293 * or %NULL if the @interface is not supported by this Object.
294 */
295 gpointer
gdome_xml_n_query_interface(GdomeNode * self,const char * interface,GdomeException * exc)296 gdome_xml_n_query_interface (GdomeNode *self, const char *interface, GdomeException *exc)
297 {
298 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
299
300 g_return_val_if_fail (priv != NULL, NULL);
301 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
302 g_return_val_if_fail (interface != NULL, NULL);
303 g_return_val_if_fail (exc != NULL, NULL);
304
305 if (!strcmp (interface, "Node") ||
306 !strcmp (interface, "EventTarget")) {
307 priv->refcnt++;
308 return self;
309 }
310 else
311 return NULL;
312 }
313
314 /**************************************
315 ***** Attributes implementation ******
316 **************************************/
317
318 /**
319 * gdome_xml_n_attributes:
320 * @self: Node Object ref
321 * @exc: Exception Object ref
322 *
323 * Returns: a NamedNodeMap containing the attributes of this node (if it is an
324 * Element) or %NULL otherwise.
325 */
326 GdomeNamedNodeMap *
gdome_xml_n_attributes(GdomeNode * self,GdomeException * exc)327 gdome_xml_n_attributes (GdomeNode *self, GdomeException *exc)
328 {
329 g_return_val_if_fail (self != NULL, NULL);
330 g_return_val_if_fail (GDOME_XML_IS_N (self), NULL);
331 g_return_val_if_fail (exc != NULL, NULL);
332
333 if (GDOME_XML_IS_EL (self))
334 return gdome_el_attributes((GdomeElement *)self, exc);
335
336 return NULL;
337 }
338
339 /**
340 * gdome_xml_n_childNodes:
341 * @self: Node Object ref
342 * @exc: Exception Object ref
343 *
344 * Returns: a NodeList that contains all children of this node. If there are no
345 * children, this is a NodeList containing no nodes. Note that attributes are
346 * not considered to be children of element nodes - use gdome_n_attributes to
347 * obtain the attributes.
348 */
349 GdomeNodeList *
gdome_xml_n_childNodes(GdomeNode * self,GdomeException * exc)350 gdome_xml_n_childNodes (GdomeNode *self, GdomeException *exc)
351 {
352 g_return_val_if_fail (self != NULL, NULL);
353 g_return_val_if_fail (GDOME_XML_IS_N (self), NULL);
354 g_return_val_if_fail (exc != NULL, NULL);
355
356 if (GDOME_XML_IS_NS(self))
357 return NULL;
358
359 return gdome_xml_nl_mkref ((GdomeNode*)self, NULL, NULL, GDOME_READONLY_NODE);
360 }
361
362 /**
363 * gdome_xml_n_firstChild:
364 * @self: Node Object ref
365 * @exc: Exception Object ref
366 *
367 * Returns: the first child of this node. If there is no such node,
368 * this returns %NULL.
369 */
370 GdomeNode *
gdome_xml_n_firstChild(GdomeNode * self,GdomeException * exc)371 gdome_xml_n_firstChild (GdomeNode *self, GdomeException *exc)
372 {
373 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
374
375 g_return_val_if_fail (priv != NULL, NULL);
376 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
377 g_return_val_if_fail (exc != NULL, NULL);
378
379 switch (gdome_xmlGetType (priv->n)) {
380 case XML_DOCUMENT_TYPE_NODE:
381 case XML_DTD_NODE:
382 case XML_PI_NODE:
383 case XML_COMMENT_NODE:
384 case XML_TEXT_NODE:
385 case XML_CDATA_SECTION_NODE:
386 case XML_NOTATION_NODE:
387 case XML_NAMESPACE_DECL:
388 return NULL;
389 case XML_DOCUMENT_NODE:
390 case XML_DOCUMENT_FRAG_NODE:
391 case XML_ENTITY_REF_NODE:
392 case XML_ELEMENT_NODE:
393 case XML_ATTRIBUTE_NODE:
394 case XML_ENTITY_NODE:
395 case XML_ENTITY_DECL:
396 return gdome_xml_n_mkref (gdome_xmlGetFirstChild (priv->n));
397 default:
398 g_warning ("gdome_xml_n_firstChild: invalid node type");
399 return NULL;
400 }
401 }
402
403 /**
404 * gdome_xml_n_lastChild:
405 * @self: Node Object ref
406 * @exc: Exception Object ref
407 *
408 * Returns: the last child of this node. If there is no such node,
409 * this returns %NULL.
410 */
411 GdomeNode *
gdome_xml_n_lastChild(GdomeNode * self,GdomeException * exc)412 gdome_xml_n_lastChild (GdomeNode *self, GdomeException *exc)
413 {
414 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
415
416 g_return_val_if_fail (priv != NULL, NULL);
417 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
418 g_return_val_if_fail (exc != NULL, NULL);
419
420 switch (gdome_xmlGetType (priv->n)) {
421 case XML_DOCUMENT_TYPE_NODE:
422 case XML_DTD_NODE:
423 case XML_PI_NODE:
424 case XML_COMMENT_NODE:
425 case XML_TEXT_NODE:
426 case XML_CDATA_SECTION_NODE:
427 case XML_NOTATION_NODE:
428 case XML_NAMESPACE_DECL:
429 return NULL;
430 case XML_DOCUMENT_NODE:
431 case XML_DOCUMENT_FRAG_NODE:
432 case XML_ENTITY_REF_NODE:
433 case XML_ELEMENT_NODE:
434 case XML_ATTRIBUTE_NODE:
435 case XML_ENTITY_NODE:
436 case XML_ENTITY_DECL:
437 return gdome_xml_n_mkref (gdome_xmlGetLastChild (priv->n));
438 default:
439 g_warning ("gdome_xml_n_lastChild: invalid node type");
440 return NULL;
441 }
442 }
443
444 /**
445 * gdome_xml_n_localName:
446 * @self: Node Objects ref
447 * @exc: Exception Object ref
448 *
449 * Returns: the local part of the qualified name of this node.
450 * For nodes of any type other than %GDOME_ELEMENT_NODE and
451 * %GDOME_ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, this is
452 * always %NULL.
453 */
454 GdomeDOMString *
gdome_xml_n_localName(GdomeNode * self,GdomeException * exc)455 gdome_xml_n_localName (GdomeNode *self, GdomeException *exc)
456 {
457 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
458
459 g_return_val_if_fail (priv != NULL, NULL);
460 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
461 g_return_val_if_fail (exc != NULL, NULL);
462
463 if((gdome_xmlGetType(priv->n) == XML_ELEMENT_NODE ||
464 gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE) &&
465 gdome_xmlGetNs(priv->n) != NULL)
466 return gdome_xml_str_mkref_dup ((gchar *)gdome_xmlGetName (priv->n));
467 else
468 return NULL;
469 }
470
471 /**
472 * gdome_xml_n_namespaceURI:
473 * @self: Node Objects ref
474 * @exc: Exception Object ref
475 *
476 * Returns: the namespace URI of this node, or %NULL if it is unspecified.
477 * For nodes of any type other than %GDOME_ELEMENT_NODE and
478 * %GDOME_ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, this is
479 * always %NULL.
480 */
481 GdomeDOMString *
gdome_xml_n_namespaceURI(GdomeNode * self,GdomeException * exc)482 gdome_xml_n_namespaceURI (GdomeNode *self, GdomeException *exc)
483 {
484 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
485
486 g_return_val_if_fail (priv != NULL, NULL);
487 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
488 g_return_val_if_fail (exc != NULL, NULL);
489
490 if((gdome_xmlGetType(priv->n) == XML_ELEMENT_NODE ||
491 gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE ||
492 gdome_xmlGetType(priv->n) == XML_NAMESPACE_DECL) &&
493 gdome_xmlGetNs(priv->n) != NULL)
494 return gdome_xml_str_mkref_dup ((gchar *)gdome_xmlGetNsURI (priv->n));
495 else
496 return NULL;
497 }
498
499 /**
500 * gdome_xml_n_nextSibling:
501 * @self: Node Object ref
502 * @exc: Exception Object ref
503 *
504 * Returns: the node immediately following this node. If there is no such
505 * node, this returns %NULL.
506 */
507 GdomeNode *
gdome_xml_n_nextSibling(GdomeNode * self,GdomeException * exc)508 gdome_xml_n_nextSibling (GdomeNode *self, GdomeException *exc)
509 {
510 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
511
512 g_return_val_if_fail (priv != NULL, NULL);
513 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
514 g_return_val_if_fail (exc != NULL, NULL);
515
516 if(GDOME_XML_IS_A (priv) || GDOME_XML_IS_NS (priv))
517 return NULL;
518 else
519 return gdome_xml_n_mkref (gdome_xmlGetNext (priv->n));
520 }
521
522 /**
523 * gdome_xml_n_nodeName:
524 * @self: Node Object ref
525 * @exc: Exception Object ref
526 *
527 * Returns: the name of this node, depending on its type.
528 */
529 GdomeDOMString *
gdome_xml_n_nodeName(GdomeNode * self,GdomeException * exc)530 gdome_xml_n_nodeName (GdomeNode *self, GdomeException *exc)
531 {
532 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
533 GdomeDOMString *ret = NULL;
534
535 g_return_val_if_fail (priv != NULL, NULL);
536 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
537 g_return_val_if_fail (exc != NULL, NULL);
538
539 switch (gdome_xmlGetType (priv->n)) {
540 case XML_ATTRIBUTE_NODE:
541 ret = gdome_a_name((GdomeAttr *)self, exc);
542 break;
543 case XML_ELEMENT_NODE:
544 ret = gdome_el_tagName((GdomeElement *)self, exc);
545 break;
546 case XML_DOCUMENT_TYPE_NODE:
547 case XML_DTD_NODE:
548 ret = gdome_dt_name((GdomeDocumentType *)self, exc);
549 break;
550 case XML_PI_NODE:
551 ret = gdome_pi_target((GdomeProcessingInstruction *)self, exc);
552 break;
553 case XML_ENTITY_NODE:
554 case XML_ENTITY_DECL: /*libxml use this instead of XML_ENTITY_NODE*/
555 case XML_ENTITY_REF_NODE:
556 case XML_NOTATION_NODE:
557 ret = gdome_xml_str_mkref_dup((gchar *)gdome_xmlGetName (priv->n));
558 break;
559 case XML_CDATA_SECTION_NODE:
560 ret = gdome_xml_str_mkref_dup("#cdata-section");
561 break;
562 case XML_COMMENT_NODE:
563 ret = gdome_xml_str_mkref_dup("#comment");
564 break;
565 case XML_DOCUMENT_NODE:
566 ret = gdome_xml_str_mkref_dup("#document");
567 break;
568 case XML_DOCUMENT_FRAG_NODE:
569 ret = gdome_xml_str_mkref_dup("#document-fragment");
570 break;
571 case XML_TEXT_NODE:
572 ret = gdome_xml_str_mkref_dup("#text");
573 break;
574 case XML_NAMESPACE_DECL:
575 ret = gdome_xml_str_mkref_dup(gdome_xmlGetNsPrefix(priv->n));
576 break;
577 default:
578 g_warning ("gdome_n_name: wrong Node Type.");
579 }
580
581 return ret;
582 }
583
584 /**
585 * gdome_xml_n_nodeType:
586 * @self: Node Object ref
587 * @exc: Exception Object ref
588 *
589 * Returns: an integer bigger than %0 representing the type of the underlying
590 * object or %0 on error.
591 */
592 unsigned short
gdome_xml_n_nodeType(GdomeNode * self,GdomeException * exc)593 gdome_xml_n_nodeType (GdomeNode *self, GdomeException *exc)
594 {
595 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
596 xmlElementType type;
597
598 g_return_val_if_fail (priv != NULL, 0);
599 g_return_val_if_fail (GDOME_XML_IS_N (priv), 0);
600 g_return_val_if_fail (exc != NULL, 0);
601
602 type = gdome_xmlGetType(priv->n);
603 if (type == XML_DTD_NODE)
604 return XML_DOCUMENT_TYPE_NODE;
605 else if (type == XML_ENTITY_DECL)
606 return XML_ENTITY_NODE;
607 else if (type == XML_NAMESPACE_DECL)
608 return GDOME_XPATH_NAMESPACE_NODE;
609 else
610 return type;
611 }
612
613 /**
614 * gdome_xml_n_nodeValue:
615 * @self: Node Object ref
616 * @exc: Exception Object ref
617 *
618 * Returns: the value of this node, depending on its type.
619 */
620 GdomeDOMString *
gdome_xml_n_nodeValue(GdomeNode * self,GdomeException * exc)621 gdome_xml_n_nodeValue (GdomeNode *self, GdomeException *exc)
622 {
623 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
624 GdomeDOMString *ret = NULL;
625
626 g_return_val_if_fail (priv != NULL, 0);
627 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
628 g_return_val_if_fail (exc != NULL, 0);
629
630 switch (gdome_xmlGetType (priv->n)) {
631 case XML_ATTRIBUTE_NODE:
632 ret = gdome_a_value ((GdomeAttr *)self, exc);
633 break;
634 case XML_PI_NODE:
635 ret = gdome_pi_data ((GdomeProcessingInstruction *)self, exc);
636 break;
637 case XML_CDATA_SECTION_NODE:
638 case XML_COMMENT_NODE:
639 case XML_TEXT_NODE:
640 ret = gdome_xml_str_mkref_own (xmlNodeGetContent (priv->n));
641 break;
642 case XML_ELEMENT_NODE:
643 case XML_ENTITY_NODE:
644 case XML_ENTITY_REF_NODE:
645 case XML_DOCUMENT_NODE:
646 case XML_DOCUMENT_TYPE_NODE:
647 case XML_DOCUMENT_FRAG_NODE:
648 case XML_NOTATION_NODE:
649 case XML_DTD_NODE:
650 case XML_ENTITY_DECL:
651 case XML_NAMESPACE_DECL:
652 break;
653 default:
654 g_warning ("could not recognize the Node Type.");
655 }
656
657 return ret;
658 }
659
660 /**
661 * gdome_xml_n_ownerDocument:
662 * @self: Node Objects ref
663 * @exc: Exception Object ref
664 *
665 * Returns: the documment object associated with this node. This is also the
666 * Document object used to create new nodes. When this node is a Document or a
667 * DocumentType which is not used with any Document yet, this is %NULL.
668 */
669 GdomeDocument *
gdome_xml_n_ownerDocument(GdomeNode * self,GdomeException * exc)670 gdome_xml_n_ownerDocument (GdomeNode *self, GdomeException *exc)
671 {
672 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
673
674 g_return_val_if_fail (priv != NULL, NULL);
675 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
676 g_return_val_if_fail (exc != NULL, NULL);
677
678 if (gdome_xmlGetType (priv->n) == XML_DOCUMENT_NODE)
679 return NULL;
680 else
681 return (GdomeDocument *)gdome_xml_n_mkref ((xmlNode *)gdome_xmlGetOwner (priv->n));
682 }
683
684 /**
685 * gdome_xml_n_parentNode:
686 * @self: Node Object ref
687 * @exc: Exception Object ref
688 *
689 * Returns: the parent of this node. All nodes, except Attr,
690 * Document, DocumentFragment, Entity, and Notation may have a parent. However,
691 * if a node has just been created and not yet added to the tree, or if it has
692 * been removed from the tree, this is %NULL.
693 */
694 GdomeNode *
gdome_xml_n_parentNode(GdomeNode * self,GdomeException * exc)695 gdome_xml_n_parentNode (GdomeNode *self, GdomeException *exc)
696 {
697 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
698
699 g_return_val_if_fail (priv != NULL, NULL);
700 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
701 g_return_val_if_fail (exc != NULL, NULL);
702
703 if(GDOME_XML_IS_TREE_N (priv))
704 return gdome_xml_n_mkref (gdome_xmlGetParent (priv->n));
705 else
706 return NULL;
707 }
708
709 /**
710 * gdome_xml_n_prefix:
711 * @self: Node Objects ref
712 * @exc: Exception Object ref
713 *
714 * Returns: the namespace prefix of this node, or %NULL if it is unspecified.
715 * For nodes of any type other than %GDOME_ELEMENT_NODE and
716 * %GDOME_ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, this is
717 * always %NULL.
718 */
719 GdomeDOMString *
gdome_xml_n_prefix(GdomeNode * self,GdomeException * exc)720 gdome_xml_n_prefix (GdomeNode *self, GdomeException *exc)
721 {
722 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
723
724 g_return_val_if_fail (priv != NULL, 0);
725 g_return_val_if_fail (GDOME_XML_IS_N (priv), 0);
726 g_return_val_if_fail (exc != NULL, 0);
727
728 if((gdome_xmlGetType(priv->n) == XML_ELEMENT_NODE ||
729 gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE ||
730 gdome_xmlGetType(priv->n) == XML_NAMESPACE_DECL) &&
731 gdome_xmlGetNs(priv->n) != NULL)
732 return gdome_xml_str_mkref_dup ((gchar *)gdome_xmlGetNsPrefix (priv->n));
733 else
734 return NULL;
735 }
736
737 /**
738 * gdome_xml_n_previousSibling:
739 * @self: Node Object ref
740 * @exc: Exception Object ref
741 *
742 * Returns: the node immediately preceding this node. If there is no such
743 * node, this returns %NULL.
744 */
745 GdomeNode *
gdome_xml_n_previousSibling(GdomeNode * self,GdomeException * exc)746 gdome_xml_n_previousSibling (GdomeNode *self, GdomeException *exc)
747 {
748 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
749
750 g_return_val_if_fail (priv != NULL, NULL);
751 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
752 g_return_val_if_fail (exc != NULL, NULL);
753
754 if(GDOME_XML_IS_A (priv) || GDOME_XML_IS_NS (priv))
755 return NULL;
756 else
757 return gdome_xml_n_mkref (gdome_xmlGetPrev (priv->n));
758 }
759
760 /**
761 * gdome_xml_n_set_nodeValue:
762 * @self: Node Object ref
763 * @nodeValue: The new value for this node.
764 * @exc: Exception Object ref
765 *
766 * Sets The value of this node, depending on its type.
767 *
768 * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
769 */
770 void
gdome_xml_n_set_nodeValue(GdomeNode * self,GdomeDOMString * nodeValue,GdomeException * exc)771 gdome_xml_n_set_nodeValue (GdomeNode *self, GdomeDOMString *nodeValue, GdomeException *exc)
772 {
773 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
774
775 g_return_if_fail (priv != NULL);
776 g_return_if_fail (GDOME_XML_IS_N (priv));
777 g_return_if_fail (nodeValue != NULL);
778 g_return_if_fail (exc != NULL);
779
780 if (GDOME_ISREADONLY (priv)) {
781 *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
782 return;
783 }
784
785 switch (gdome_xmlGetType(priv->n)) {
786 case XML_ATTRIBUTE_NODE:
787 gdome_xml_a_set_value ((GdomeAttr *)self, nodeValue, exc);
788 break;
789 case XML_PI_NODE:
790 gdome_xml_pi_set_data ((GdomeProcessingInstruction *)self, nodeValue, exc);
791 break;
792 case XML_CDATA_SECTION_NODE:
793 case XML_COMMENT_NODE:
794 case XML_TEXT_NODE:
795 gdome_xml_cd_set_data ((GdomeCharacterData *)self, nodeValue, exc);
796 break;
797 case XML_ELEMENT_NODE:
798 case XML_ENTITY_NODE:
799 case XML_ENTITY_REF_NODE:
800 case XML_DOCUMENT_NODE:
801 case XML_DOCUMENT_TYPE_NODE:
802 case XML_DOCUMENT_FRAG_NODE:
803 case XML_NOTATION_NODE:
804 case XML_DTD_NODE:
805 case XML_NAMESPACE_DECL:
806 break;
807 default:
808 g_warning ("could not recognize the Node Type.");
809 }
810 }
811
812 /**
813 * gdome_xml_n_set_prefix:
814 * @self: Node Object ref
815 * @prefix: The new prefix for this node.
816 * @exc: Exception Object ref
817 *
818 * Sets a new nemaspace prefix for this node.
819 *
820 * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
821 * %GDOME_NAMESPACE_ERR: Raised if the specified @prefix is malformed per the
822 * Namespaces in XML specification, if the namespaceURI of this node is %NULL,
823 * if the specified prefix is "xml" and the namespaceURI of this node is
824 * different from "http://www.w3.org/XML/1998/namespace", if this node is an
825 * attribute and the specified prefix is "xmlns" and the namespaceURI of this
826 * node is different from "http://www.w3.org/2000/xmlns/", or if this node is
827 * an attribute and the qualifiedName of this node is "xmlns".
828 */
829 void
gdome_xml_n_set_prefix(GdomeNode * self,GdomeDOMString * prefix,GdomeException * exc)830 gdome_xml_n_set_prefix (GdomeNode *self, GdomeDOMString *prefix, GdomeException *exc)
831 {
832 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
833 xmlNs *ns;
834
835 g_return_if_fail (priv != NULL);
836 g_return_if_fail (GDOME_XML_IS_N (priv));
837 g_return_if_fail (prefix != NULL);
838 g_return_if_fail (exc != NULL);
839
840 if (GDOME_ISREADONLY (priv)) {
841 *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
842 return;
843 }
844
845 if((gdome_xmlGetType(priv->n) == XML_ELEMENT_NODE ||
846 gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE) &&
847 gdome_xmlGetNs(priv->n) != NULL &&
848 !xmlStrEqual(gdome_xmlGetNsPrefix (priv->n), (xmlChar *)prefix->str)) {
849
850 /* tests for NAMESPACE_ERR */
851 gchar *nsURI = (gchar *)gdome_xmlGetNsURI (priv->n);
852 if (nsURI == NULL ||
853 (!strcmp (prefix->str, "xml") &&
854 strcmp (nsURI, "http://www.w3.org/XML/1998/namespace")) ||
855 (gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE &&
856 !strcmp (prefix->str, "xmlns") &&
857 strcmp (nsURI, GDOME_XMLNS_NAMESPACE)) ||
858 (gdome_xmlGetType(priv->n) == XML_ATTRIBUTE_NODE &&
859 !strcmp (gdome_xmlGetName(priv->n), "xmlns"))) {
860 *exc = GDOME_NAMESPACE_ERR;
861 return;
862 }
863 ns = gdome_xmlNewNs (priv->n->doc, gdome_xmlGetNsURI (priv->n), (xmlChar *)prefix->str);
864 gdome_xmlSetNs(priv->n, ns);
865 }
866 }
867
868 /**************************************
869 ******* Methods implementation *******
870 **************************************/
871
872 /**
873 * gdome_xml_n_appendChild:
874 * @self: Node Object ref
875 * @newChild: The node to add
876 * @exc: Exception Object ref
877 *
878 * Adds the node @newChild to the end of the list of children of this node.
879 * If the @newChild is already in the tree, it is first removed. If it is a
880 * DocumentFragment node, the entire contents of the document fragment are
881 * moved into the child list of this node
882 *
883 * %GDOME_HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
884 * allow children of the type of the @newChild node, or if the node to append is
885 * one of this node's ancestors or this node itself.
886 * %GDOME_WRONG_DOCUMENT_ERR: Raised if @newChild was created from a different
887 * document than the one that created this node.
888 * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
889 * Returns: the node added.
890 */
891 GdomeNode *
gdome_xml_n_appendChild(GdomeNode * self,GdomeNode * newChild,GdomeException * exc)892 gdome_xml_n_appendChild (GdomeNode *self, GdomeNode *newChild, GdomeException *exc)
893 {
894 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
895 Gdome_xml_Node *new_priv = (Gdome_xml_Node *)newChild;
896 GdomeMutationEvent *mev;
897 xmlNode *ret;
898
899 g_return_val_if_fail (priv != NULL, NULL);
900 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
901 g_return_val_if_fail (new_priv != NULL, NULL);
902 g_return_val_if_fail (GDOME_XML_IS_N (new_priv), NULL);
903 g_return_val_if_fail (exc != NULL, NULL);
904
905 if (!gdome_xml_n_canAppend (self, newChild, exc)) {
906 *exc = GDOME_HIERARCHY_REQUEST_ERR;
907 return NULL;
908 }
909
910 if (gdome_xmlGetOwner(new_priv->n) != gdome_xmlGetOwner(priv->n)) {
911 *exc = GDOME_WRONG_DOCUMENT_ERR;
912 return NULL;
913 }
914
915 if (GDOME_ISREADONLY (priv)) {
916 *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
917 return NULL;
918 }
919
920 /* If the newChild is already in the tree, it is first removed. */
921 if (gdome_xmlGetParent(new_priv->n) != NULL)
922 gdome_xmlUnlinkChild(gdome_xmlGetParent(new_priv->n), new_priv->n);
923
924 ret = gdome_xmlAppendChild(priv->n, new_priv->n);
925
926 /* Delete children list for DocumentFragment Node */
927 if (gdome_xmlGetType (new_priv->n) == XML_DOCUMENT_FRAG_NODE) {
928 gdome_xmlSetFirstChild(new_priv->n, NULL);
929 gdome_xmlSetLastChild(new_priv->n, NULL);
930 }
931
932 if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_INSERTED_EVENT_TYPE)) {
933 /* Fire DOMNodeInserted */
934 mev = gdome_evt_mevnt_mkref ();
935 gdome_xml_n_ref (self, exc);
936 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_INSERTED_EVENT_TYPE,
937 TRUE, FALSE, self,
938 NULL, NULL, NULL, 0, exc);
939 gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
940 gdome_xml_n_unref (self, exc);
941 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
942 }
943
944 if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_INSERTED_INTO_DOCUMENT_EVENT_TYPE)) {
945 /* Fire DOMNodeInsertedIntoDocument */
946 mev = gdome_evt_mevnt_mkref ();
947 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_INSERTED_INTO_DOCUMENT_EVENT_TYPE,
948 FALSE, FALSE, NULL,
949 NULL, NULL, NULL, 0, exc);
950 gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
951 gdome_xml_n_subTreeDispatchEvent (newChild, (GdomeEvent *)mev, exc);
952 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
953 }
954
955 if (gdome_xml_n_eventEnabledByCode (self, DOM_SUBTREE_MODIFIED_EVENT_TYPE)) {
956 /* Fire DOMSubtreeModified */
957 mev = gdome_evt_mevnt_mkref ();
958 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_SUBTREE_MODIFIED_EVENT_TYPE,
959 TRUE, FALSE, NULL,
960 NULL, NULL, NULL, 0, exc);
961 gdome_xml_n_dispatchEvent (self, (GdomeEvent *)mev, exc);
962 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
963 }
964
965 return gdome_xml_n_mkref (ret);
966 }
967
968 /**
969 * gdome_xml_n_cloneNode:
970 * @self: Node Object ref
971 * @deep: If true, recursively clone the subtree under the specified node;
972 * if false, clone only the node itself (and its attributes, if it is
973 * an Element).
974 * @exc: Exception Object ref
975 *
976 * Makes a duplicate of this node, i.e., serves as a generic copy
977 * constructor for nodes. The duplicate node has no parent; (parentNode is
978 * %NULL).
979 * %GDOME_DOCUMENT_TYPE_NODE, %GDOME_NOTATION_NODE and %GDOME_ENTITY_NODE
980 * nodes are not supported.
981 *
982 * %GDOME_NOT_SUPPORTED_ERR: Raised if the type of node being cloned is not
983 * supported.
984 * Returns: the duplicate node.
985 */
986 GdomeNode *
gdome_xml_n_cloneNode(GdomeNode * self,GdomeBoolean deep,GdomeException * exc)987 gdome_xml_n_cloneNode (GdomeNode *self, GdomeBoolean deep, GdomeException *exc)
988 {
989 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
990 xmlNode *n = NULL;
991 xmlElementType type;
992
993 g_return_val_if_fail (priv != NULL, NULL);
994 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
995 g_return_val_if_fail (exc != NULL, NULL);
996
997 type = gdome_xmlGetType (priv->n);
998 if (type == XML_ENTITY_NODE ||
999 type == XML_ENTITY_DECL ||
1000 type == XML_NOTATION_NODE ||
1001 type == XML_DOCUMENT_TYPE_NODE ||
1002 type == XML_DTD_NODE ||
1003 type == XML_NAMESPACE_DECL )
1004 *exc = GDOME_NOT_SUPPORTED_ERR;
1005 else if (type == XML_DOCUMENT_NODE)
1006 n = (xmlNode *)xmlCopyDoc ((xmlDoc *)priv->n, deep);
1007 else if (type == XML_ATTRIBUTE_NODE) {
1008 n = (xmlNode *)xmlCopyProp (NULL, (xmlAttr *)priv->n);
1009 if (gdome_xmlGetOwner (n) == NULL)
1010 gdome_xmlSetOwner (n , gdome_xmlGetOwner (priv->n));
1011 }
1012 else
1013 n = xmlDocCopyNode (priv->n, gdome_xmlGetOwner(priv->n), deep);
1014
1015 if (*exc)
1016 return NULL;
1017 else
1018 return gdome_xml_n_mkref (n);
1019 }
1020
1021 /**
1022 * gdome_xml_n_hasAttributes:
1023 * @self: Node Object ref
1024 * @exc: Exception Object ref
1025 *
1026 * Returns: %TRUE if this node has any attributes, %FALSE otherwise.
1027 */
1028 GdomeBoolean
gdome_xml_n_hasAttributes(GdomeNode * self,GdomeException * exc)1029 gdome_xml_n_hasAttributes (GdomeNode *self, GdomeException *exc) {
1030 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1031
1032 g_return_val_if_fail (priv != NULL, 0);
1033 g_return_val_if_fail (GDOME_XML_IS_N (priv), 0);
1034 g_return_val_if_fail (exc != NULL, 0);
1035
1036 if (GDOME_XML_IS_EL (priv))
1037 return (gdome_xmlGetAttrList (priv->n) != NULL);
1038 else
1039 return FALSE;
1040 }
1041
1042 /**
1043 * gdome_xml_n_hasChildNodes:
1044 * @self: Node Object ref
1045 * @exc: Exception Object ref
1046 *
1047 * Returns: %TRUE if this node has any children, %FALSE otherwise.
1048 */
1049 GdomeBoolean
gdome_xml_n_hasChildNodes(GdomeNode * self,GdomeException * exc)1050 gdome_xml_n_hasChildNodes (GdomeNode *self, GdomeException *exc) {
1051 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1052
1053 g_return_val_if_fail (priv != NULL, 0);
1054 g_return_val_if_fail (GDOME_XML_IS_N (priv), 0);
1055 g_return_val_if_fail (exc != NULL, 0);
1056
1057 switch (gdome_xmlGetType (priv->n)) {
1058 case XML_DOCUMENT_TYPE_NODE:
1059 case XML_DTD_NODE:
1060 case XML_PI_NODE:
1061 case XML_COMMENT_NODE:
1062 case XML_TEXT_NODE:
1063 case XML_CDATA_SECTION_NODE:
1064 case XML_NOTATION_NODE:
1065 case XML_NAMESPACE_DECL:
1066 return FALSE;
1067 case XML_DOCUMENT_NODE:
1068 case XML_DOCUMENT_FRAG_NODE:
1069 case XML_ENTITY_REF_NODE:
1070 case XML_ELEMENT_NODE:
1071 case XML_ATTRIBUTE_NODE:
1072 case XML_ENTITY_NODE:
1073 case XML_ENTITY_DECL:
1074 return (gdome_xmlGetFirstChild (priv->n) != NULL);
1075 default:
1076 g_warning ("gdome_xml_n_hasChildNodes: invalid node type");
1077 return FALSE;
1078 }
1079 }
1080
1081 /**
1082 * gdome_xml_n_insertBefore:
1083 * @self: Node Object ref
1084 * @newChild: The new node to put in the child list
1085 * @refChild: the reference node, i.e., the node before which the new node
1086 * must be inserted.
1087 * @exc: Exception Object ref
1088 *
1089 * Inserts the node @newChild before the existing child node @refChild. If
1090 * @refChild is %NULL, insert @newChild at the end of the list of children.
1091 * If @newChild is a DocumentFragment node, all of its children are inserted,
1092 * in the same order, before @refChild. If the @newChild is already in the
1093 * tree, it is first removed.
1094 *
1095 * %GDOME_HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does not
1096 * allow children of the type of the @newChild node, or if the node to insert is
1097 * one of this node's ancestors or this node itself.
1098 * %GDOME_WRONG_DOCUMENT_ERR: Raised if @newChild was created from a different
1099 * document than the one that created this node.
1100 * %GDOME_NOT_FOUND_ERR: Raised if @refChild is not a child of this node.
1101 * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1102 * Returns: the node being inserted.
1103 */
1104 GdomeNode *
gdome_xml_n_insertBefore(GdomeNode * self,GdomeNode * newChild,GdomeNode * refChild,GdomeException * exc)1105 gdome_xml_n_insertBefore (GdomeNode *self, GdomeNode *newChild, GdomeNode *refChild, GdomeException *exc)
1106 {
1107 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1108 Gdome_xml_Node *new_priv = (Gdome_xml_Node *)newChild;
1109 Gdome_xml_Node *ref_priv = (Gdome_xml_Node *)refChild;
1110 GdomeMutationEvent *mev;
1111 xmlNode *ret = NULL;
1112
1113 g_return_val_if_fail (priv != NULL, NULL);
1114 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
1115 g_return_val_if_fail (new_priv != NULL, NULL);
1116 g_return_val_if_fail (GDOME_XML_IS_N (new_priv), NULL);
1117 g_return_val_if_fail (exc != NULL, NULL);
1118
1119 if (!gdome_xml_n_canAppend (self, newChild, exc)) {
1120 *exc = GDOME_HIERARCHY_REQUEST_ERR;
1121 return NULL;
1122 }
1123
1124 if (gdome_xmlGetOwner(new_priv->n) != gdome_xmlGetOwner(priv->n)) {
1125 *exc = GDOME_WRONG_DOCUMENT_ERR;
1126 return NULL;
1127 }
1128
1129 if (GDOME_ISREADONLY (priv)) {
1130 *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
1131 return NULL;
1132 }
1133
1134 /* If refChild is null, insert newChild at the end of the list of children.*/
1135 if(ref_priv == NULL)
1136 return gdome_xml_n_appendChild (self, newChild, exc);
1137 else
1138 g_return_val_if_fail (GDOME_XML_IS_N (ref_priv), NULL);
1139
1140 /* If the newChild is already in the tree, it is first removed. */
1141 if (gdome_xmlGetParent(new_priv->n) != NULL) {
1142 if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_REMOVED_EVENT_TYPE)) {
1143 /* Fire DOMNodeRemoved */
1144 mev = gdome_evt_mevnt_mkref ();
1145 gdome_xml_n_ref (self, exc);
1146 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_REMOVED_EVENT_TYPE,
1147 TRUE, FALSE, self,
1148 NULL, NULL, NULL, 0, exc);
1149 gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
1150 gdome_xml_n_unref (self, exc);
1151 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1152 }
1153
1154 if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_REMOVED_FROM_DOCUMENT_EVENT_TYPE)) {
1155 /* Fire DOMNodeRemovedFromDocument */
1156 mev = gdome_evt_mevnt_mkref ();
1157 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_REMOVED_FROM_DOCUMENT_EVENT_TYPE,
1158 FALSE, FALSE, NULL,
1159 NULL, NULL, NULL, 0, exc);
1160 gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
1161 gdome_xml_n_subTreeDispatchEvent (newChild, (GdomeEvent *)mev, exc);
1162 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1163 }
1164
1165 gdome_xmlUnlinkChild(gdome_xmlGetParent(new_priv->n), new_priv->n);
1166 }
1167
1168 if ((ret = gdome_xmlInsertBeforeChild(priv->n, new_priv->n, ref_priv->n)) == NULL) {
1169 *exc = GDOME_NOT_FOUND_ERR;
1170 return NULL;
1171 }
1172
1173 /* Unlink children list for DocumentFragment Node */
1174 if (gdome_xmlGetType (new_priv->n) == XML_DOCUMENT_FRAG_NODE) {
1175 gdome_xmlSetFirstChild(new_priv->n, NULL);
1176 gdome_xmlSetLastChild(new_priv->n, NULL);
1177 }
1178
1179 if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_INSERTED_EVENT_TYPE)) {
1180 /* Fire DOMNodeInserted */
1181 mev = gdome_evt_mevnt_mkref ();
1182 gdome_xml_n_ref (self, exc);
1183 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_INSERTED_EVENT_TYPE,
1184 TRUE, FALSE, self,
1185 NULL, NULL, NULL, 0, exc);
1186 gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
1187 gdome_xml_n_unref (self, exc);
1188 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1189 }
1190
1191 if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_INSERTED_INTO_DOCUMENT_EVENT_TYPE)) {
1192 /* Fire DOMNodeInsertedIntoDocument */
1193 mev = gdome_evt_mevnt_mkref ();
1194 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_INSERTED_INTO_DOCUMENT_EVENT_TYPE,
1195 FALSE, FALSE, NULL,
1196 NULL, NULL, NULL, 0, exc);
1197 gdome_xml_n_dispatchEvent (newChild, (GdomeEvent *)mev, exc);
1198 gdome_xml_n_subTreeDispatchEvent (newChild, (GdomeEvent *)mev, exc);
1199 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1200 }
1201
1202 if (gdome_xml_n_eventEnabledByCode (self, DOM_SUBTREE_MODIFIED_EVENT_TYPE)) {
1203 /* Fire DOMSubtreeModified */
1204 mev = gdome_evt_mevnt_mkref ();
1205 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_SUBTREE_MODIFIED_EVENT_TYPE,
1206 TRUE, FALSE, NULL,
1207 NULL, NULL, NULL, 0, exc);
1208 gdome_xml_n_dispatchEvent (self, (GdomeEvent *)mev, exc);
1209 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1210 }
1211
1212 return gdome_xml_n_mkref (ret);
1213 }
1214
1215 /**
1216 * gdome_xml_n_isSupported:
1217 * @self: Node Object ref
1218 * @feature: The name of the feature to test.
1219 * @version: This is the version number of the feature to test. In Level 2,
1220 * version 1, this is the string "2.0". If the version is not
1221 * specified, supporting any version of the feature will cause the
1222 * method to return %TRUE.
1223 * @exc: Exception Object ref
1224 *
1225 * Tests whether the DOM implementation implements a specific feature and that
1226 * feature is supported by this node.
1227 * Returns: %TRUE if the specified feature is supported on this node, %FALSE
1228 * otherwise.
1229 */
1230 GdomeBoolean
gdome_xml_n_isSupported(GdomeNode * self,GdomeDOMString * feature,GdomeDOMString * version,GdomeException * exc)1231 gdome_xml_n_isSupported (GdomeNode *self, GdomeDOMString *feature, GdomeDOMString *version, GdomeException *exc)
1232 {
1233 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1234 GdomeBoolean ret;
1235 GdomeDOMImplementation *domimpl;
1236
1237 g_return_val_if_fail (priv != NULL, FALSE);
1238 g_return_val_if_fail (GDOME_XML_IS_N (priv), FALSE);
1239 g_return_val_if_fail (feature != NULL, FALSE);
1240 g_return_val_if_fail (exc != NULL, FALSE);
1241
1242 if (version == NULL)
1243 return TRUE;
1244
1245 domimpl = gdome_xml_di_mkref();
1246 ret = gdome_xml_di_hasFeature (domimpl, feature, version, exc);
1247 gdome_xml_di_unref (domimpl, exc);
1248
1249 return ret;
1250 }
1251
1252 /**
1253 * gdome_xml_n_normalize:
1254 * @self: Node Object ref
1255 * @exc: Exception Object ref
1256 *
1257 * Puts all Text nodes in the full depth of the sub-tree underneath this Node,
1258 * including attribute nodes, into a "normal" form where only structure (e.g.,
1259 * elements, comments, processing instructions, CDATA sections, and entity
1260 * references) separates Text nodes, i.e., there are neither adjacent Text
1261 * nodes nor empty Text nodes.
1262 */
1263 void
gdome_xml_n_normalize(GdomeNode * self,GdomeException * exc)1264 gdome_xml_n_normalize (GdomeNode *self, GdomeException *exc)
1265 {
1266 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1267 GdomeNode *child = NULL, *new_child = NULL;
1268 GdomeNode *next = NULL, *new_next = NULL;
1269 GdomeDOMString *str = NULL;
1270 GdomeNode *result = NULL;
1271
1272 g_return_if_fail (priv != NULL);
1273 g_return_if_fail (GDOME_XML_IS_N (priv));
1274 g_return_if_fail (exc != NULL);
1275
1276 /* this is a generic implementation, not optimized for speed */
1277 child = gdome_n_firstChild (self, exc);
1278 while (child != NULL) {
1279 unsigned short type;
1280
1281 type = gdome_n_nodeType (child, exc);
1282 if (type == GDOME_TEXT_NODE) {
1283 next = gdome_n_nextSibling (child, exc);
1284 while (next != NULL) {
1285 if (gdome_n_nodeType (next, exc) != GDOME_TEXT_NODE) {
1286 gdome_n_unref (next, exc);
1287 break;
1288 }
1289 str = gdome_cd_data ((GdomeCharacterData *)next, exc);
1290 gdome_cd_appendData ((GdomeCharacterData *)child, str, exc);
1291 gdome_str_unref (str);
1292 new_next = gdome_n_nextSibling (next, exc);
1293 result = gdome_n_removeChild (self, next, exc);
1294 gdome_n_unref (result, exc);
1295 gdome_n_unref (next, exc);
1296 next = new_next;
1297 }
1298 } else if (type == GDOME_ELEMENT_NODE) {
1299 GdomeNamedNodeMap *nnm;
1300 gulong i, n;
1301
1302 gdome_n_normalize (child, exc);
1303 nnm = gdome_n_attributes (child, exc);
1304 n = gdome_nnm_length (nnm, exc);
1305 for (i = 0; i < n; i++) {
1306 GdomeNode *attr;
1307
1308 attr = gdome_nnm_item (nnm, i, exc);
1309 gdome_n_normalize (attr, exc);
1310 gdome_n_unref (attr, exc);
1311 }
1312 gdome_nnm_unref (nnm, exc);
1313 }
1314 new_child = gdome_n_nextSibling (child, exc);
1315 gdome_n_unref (child, exc);
1316 child = new_child;
1317 }
1318 }
1319
1320 /**
1321 * gdome_xml_n_removeChild:
1322 * @self: Node Object ref
1323 * @oldChild: The node being removed
1324 * @exc: Exception Object ref
1325 *
1326 * Removes the child node indicated by @oldChild from the list of children, and
1327 * returns it.
1328 *
1329 * %GDOME_NOT_FOUND_ERR: Raised if @oldChild is not a child of this node.
1330 * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1331 * Returns: the node removed.
1332 */
1333 GdomeNode *
gdome_xml_n_removeChild(GdomeNode * self,GdomeNode * oldChild,GdomeException * exc)1334 gdome_xml_n_removeChild (GdomeNode *self, GdomeNode *oldChild, GdomeException *exc)
1335 {
1336 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1337 Gdome_xml_Node *old_priv = (Gdome_xml_Node *)oldChild;
1338 GdomeMutationEvent *mev;
1339 xmlNode *ret;
1340
1341 g_return_val_if_fail (priv != NULL, NULL);
1342 g_return_val_if_fail (GDOME_XML_IS_N (priv), NULL);
1343 g_return_val_if_fail (old_priv != NULL, NULL);
1344 g_return_val_if_fail (GDOME_XML_IS_TREE_N (old_priv), NULL);
1345 g_return_val_if_fail (exc != NULL, NULL);
1346
1347 if (GDOME_ISREADONLY (priv)) {
1348 *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
1349 return NULL;
1350 }
1351
1352 if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_REMOVED_EVENT_TYPE)) {
1353 /* Fire DOMNodeRemoved */
1354 mev = gdome_evt_mevnt_mkref ();
1355 gdome_xml_n_ref (self, exc);
1356 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_REMOVED_EVENT_TYPE,
1357 TRUE, FALSE, self,
1358 NULL, NULL, NULL, 0, exc);
1359 gdome_xml_n_dispatchEvent (oldChild, (GdomeEvent *)mev, exc);
1360 gdome_xml_n_unref (self, exc);
1361 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1362 }
1363
1364 if (gdome_xml_n_eventEnabledByCode (self, DOM_NODE_REMOVED_FROM_DOCUMENT_EVENT_TYPE)) {
1365 /* Fire DOMNodeRemovedFromDocument */
1366 mev = gdome_evt_mevnt_mkref ();
1367 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_NODE_REMOVED_FROM_DOCUMENT_EVENT_TYPE,
1368 FALSE, FALSE, NULL,
1369 NULL, NULL, NULL, 0, exc);
1370 gdome_xml_n_dispatchEvent (oldChild, (GdomeEvent *)mev, exc);
1371 gdome_xml_n_subTreeDispatchEvent (oldChild, (GdomeEvent *)mev, exc);
1372 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1373 }
1374
1375 if (gdome_xml_n_eventEnabledByCode (self, DOM_SUBTREE_MODIFIED_EVENT_TYPE)) {
1376 /* Fire DOMSubtreeModified */
1377 mev = gdome_evt_mevnt_mkref ();
1378 gdome_evt_mevnt_initMutationEventByCode (mev, DOM_SUBTREE_MODIFIED_EVENT_TYPE,
1379 TRUE, FALSE, NULL,
1380 NULL, NULL, NULL, 0, exc);
1381 gdome_xml_n_dispatchEvent (self, (GdomeEvent *)mev, exc);
1382 gdome_evt_mevnt_unref ((GdomeEvent *)mev, exc);
1383 }
1384
1385 if ((ret = gdome_xmlUnlinkChild(priv->n, old_priv->n)) == NULL) {
1386 *exc = GDOME_NOT_FOUND_ERR;
1387 return NULL;
1388 }
1389
1390 return gdome_xml_n_mkref (ret);
1391 }
1392
1393 /**
1394 * gdome_xml_n_replaceChild:
1395 * @self: Node Object ref
1396 * @newChild: The new node to put in the child list
1397 * @oldChild: The node being replaced in the list
1398 * @exc: Exception Object ref
1399 *
1400 * Replaces the child node @oldChild with @newChild in the list of children,
1401 * and returns the @oldChild node. If @newChild is a DocumentFragment object,
1402 * @oldChild is replaced by all of the DocumentFragment children, which are
1403 * inserted in the same order. If the @newChild is already in the tree, it is
1404 * first removed.
1405 *
1406 * %GDOME_HIERARCHY_REQUEST_ERR: Raised if this node is of a type that does
1407 * not allow children of the type of the @newChild node, or if the node to put
1408 * in is one of this node's ancestors or this node itself.
1409 * %GDOME_WRONG_DOCUMENT_ERR: Raised if @newChild was created from a different
1410 * document than the one that created this node.
1411 * %GDOME_NOT_FOUND_ERR: Raised if @oldChild is not a child of this node.
1412 * %GDOME_NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1413 * Returns: the node replaced.
1414 */
1415 GdomeNode *
gdome_xml_n_replaceChild(GdomeNode * self,GdomeNode * newChild,GdomeNode * oldChild,GdomeException * exc)1416 gdome_xml_n_replaceChild (GdomeNode *self, GdomeNode *newChild, GdomeNode *oldChild, GdomeException *exc)
1417 {
1418 GdomeNode *ret = NULL;
1419 GdomeNode *refChild = NULL;
1420
1421 g_return_val_if_fail (self != NULL, NULL);
1422 g_return_val_if_fail (GDOME_XML_IS_N (self), NULL);
1423 g_return_val_if_fail (newChild != NULL, NULL);
1424 g_return_val_if_fail (GDOME_XML_IS_N (newChild), NULL);
1425 g_return_val_if_fail (oldChild != NULL, NULL);
1426 g_return_val_if_fail (GDOME_XML_IS_N (oldChild), NULL);
1427 g_return_val_if_fail (exc != NULL, NULL);
1428
1429 if (GDOME_ISREADONLY (self)) {
1430 *exc = GDOME_NO_MODIFICATION_ALLOWED_ERR;
1431 return NULL;
1432 }
1433
1434 refChild = gdome_n_nextSibling (oldChild, exc);
1435 if (gdome_n_removeChild (self, oldChild, exc)) {
1436 if (gdome_n_insertBefore (self, newChild, refChild, exc)) {
1437 gdome_n_unref (newChild, exc);
1438 ret = oldChild;
1439 } else {
1440 gdome_n_unref (oldChild, exc);
1441 ret = NULL;
1442 }
1443 }
1444
1445 if (refChild)
1446 gdome_n_unref (refChild, exc);
1447
1448 return ret;
1449 }
1450
1451 /**
1452 * gdome_xml_n_addEventListener:
1453 * @self: Node Object ref
1454 * @type: the event type for which the user is registering
1455 * @listener: the listener parameter takes an interface implemented by the
1456 * user which contains the methods to be called when the event occurs.
1457 * @useCapture: if %TRUE, useCapture indicates that the user wishes to initiate
1458 * capture. After initiating capture, all events of the specified
1459 * type will be dispatched to the registered EventListener before
1460 * being dispatched to any EventTargets beneath them in the tree.
1461 * Events which are bubbling upward through the tree will not
1462 * trigger an EventListener designated to use capture.
1463 * @exc: Exception Object ref
1464 *
1465 * This method allows the registration of event listeners on the event target.
1466 * If an EventListener is added to an EventTarget while it is processing an
1467 * event, it will not be triggered by the current actions but may be triggered
1468 * during a later stage of event flow, such as the bubbling phase.
1469 * If multiple identical EventListeners are registered on the same EventTarget
1470 * with the same parameters the duplicate instances are discarded. They do not
1471 * cause the EventListener to be called twice and since they are discarded
1472 * they do not need to be removed with the removeEventListener method.
1473 */
1474 void
gdome_xml_n_addEventListener(GdomeNode * self,GdomeDOMString * type,GdomeEventListener * listener,GdomeBoolean useCapture,GdomeException * exc)1475 gdome_xml_n_addEventListener (GdomeNode *self, GdomeDOMString *type,
1476 GdomeEventListener *listener, GdomeBoolean useCapture,
1477 GdomeException *exc)
1478 {
1479 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1480 Gdome_xml_ListenerList *ll = NULL;
1481 Gdome_xml_ListenerList *temp;
1482 guint32 codeType;
1483
1484 g_return_if_fail (priv != NULL);
1485 g_return_if_fail (GDOME_XML_IS_N (priv));
1486 g_return_if_fail (listener != NULL);
1487 g_return_if_fail (type != NULL);
1488 g_return_if_fail (exc != NULL);
1489
1490 /* duplicate instances are discarted */
1491 codeType = gdome_evt_evnt_codeOfName (type->str);
1492 temp = priv->ll;
1493 while (temp) {
1494 if (temp->listener == listener &&
1495 temp->type == codeType &&
1496 temp->useCapture == useCapture) {
1497 return;
1498 }
1499 temp = temp->next;
1500 }
1501
1502 /* create a new ListenerList entry*/
1503 ll = g_new (Gdome_xml_ListenerList, 1);
1504 ll->type = codeType;
1505 gdome_evt_evntl_ref (listener, exc);
1506 ll->listener = listener;
1507 ll->useCapture = useCapture;
1508
1509 /* add it at begin of the ListenerList of the target */
1510 ll->next = priv->ll;
1511 priv->ll = ll;
1512 }
1513
1514 /**
1515 * gdome_xml_n_removeEventListener:
1516 * @self: Node Object ref
1517 * @type: Specifies the event type of the EventListener being removed.
1518 * @listener: The EventListener parameter indicates the EventListener to be
1519 * removed.
1520 * @useCapture: Specifies whether the EventListener being removed was
1521 * registered as a capturing listener or not. If a listener was
1522 * registered twice, one with capture and one without, each must
1523 * be removed separately. Removal of a capturing listener does
1524 * not affect a non-capturing version of the same listener, and
1525 * vice versa.
1526 * @exc: Exception Object ref
1527 *
1528 * This method allows the removal of event listeners from the event target. If
1529 * an EventListener is removed from an EventTarget while it is processing an
1530 * event, it will not be triggered by the current actions. EventListeners can
1531 * never be invoked after being removed. Calling removeEventListener with
1532 * arguments which do not identify any currently registered EventListener on
1533 * the EventTarget has no effect.
1534 */
1535 void
gdome_xml_n_removeEventListener(GdomeNode * self,GdomeDOMString * type,GdomeEventListener * listener,GdomeBoolean useCapture,GdomeException * exc)1536 gdome_xml_n_removeEventListener (GdomeNode *self, GdomeDOMString *type,
1537 GdomeEventListener *listener, GdomeBoolean useCapture,
1538 GdomeException *exc)
1539 {
1540 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1541 Gdome_xml_ListenerList *temp, *prev = NULL;
1542 guint32 codeType;
1543
1544 g_return_if_fail (priv != NULL);
1545 g_return_if_fail (GDOME_XML_IS_N (priv));
1546 g_return_if_fail (listener != NULL);
1547 g_return_if_fail (type != NULL);
1548 g_return_if_fail (exc != NULL);
1549
1550 codeType = gdome_evt_evnt_codeOfName (type->str);
1551 temp = priv->ll;
1552 while (temp) {
1553 if (useCapture == temp->useCapture &&
1554 temp->listener == listener &&
1555 temp->type == codeType) {
1556 if (prev)
1557 prev->next = temp->next;
1558 else {
1559 g_assert (priv->ll == temp);
1560 priv->ll = priv->ll->next;
1561 }
1562 temp->next = NULL;
1563 gdome_evt_evntl_unref (listener, exc);
1564 g_free (temp);
1565 break;
1566 }
1567 prev = temp;
1568 temp = temp->next;
1569 }
1570 }
1571
1572
1573 /**
1574 * gdome_xml_n_dispatchEvent:
1575 * @self: Node Object ref
1576 * @evt: Specifies the event type, behavior, and contextual information to be
1577 * used in processing the event.
1578 * @exc: Exception Object ref
1579 *
1580 * This method allows the dispatch of events into the implementations event
1581 * model. Events dispatched in this manner will have the same capturing and
1582 * bubbling behavior as events dispatched directly by the implementation. The
1583 * target of the event is the EventTarget on which dispatchEvent is called.
1584 *
1585 * GDOME_UNSPECIFIED_EVENT_TYPE_ERR: Raised if the Event's type was not
1586 * specified by initializing the event before dispatchEvent was called.
1587 * Specification of the Event's type as %NULL or an empty string will also
1588 * trigger this exception.
1589 * Returns: if preventDefault was called the value is %FALSE, else the value
1590 * is %TRUE.
1591 */
1592 GdomeBoolean
gdome_xml_n_dispatchEvent(GdomeNode * self,GdomeEvent * evt,GdomeException * exc)1593 gdome_xml_n_dispatchEvent (GdomeNode *self, GdomeEvent *evt, GdomeException *exc)
1594 {
1595 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1596 Gdome_evt_Event *ev_priv = (Gdome_evt_Event *)evt;
1597
1598 g_return_val_if_fail (priv != NULL, FALSE);
1599 g_return_val_if_fail (GDOME_XML_IS_N (priv), FALSE);
1600 g_return_val_if_fail (evt != NULL, FALSE);
1601 g_return_val_if_fail (exc != NULL, FALSE);
1602
1603 if (ev_priv->type == 0) {
1604 *exc = GDOME_EVENT_EXCEPTION + GDOME_UNSPECIFIED_EVENT_TYPE_ERR;
1605 return FALSE;
1606 }
1607
1608 gdome_xml_n_ref (self, exc);
1609 ev_priv->target = self;
1610 gdome_evt_fireEvent (evt);
1611 gdome_xml_n_unref (self, exc);
1612
1613 return !ev_priv->default_prevented;
1614 }
1615
1616 /**
1617 * gdome_xml_n_subTreeDispatchEvent:
1618 * @self: Node Object ref
1619 * @evt: Specifies the event type, behavior, and contextual information to be
1620 * used in processing the event.
1621 * @exc: Exception Object ref
1622 *
1623 * This method allows the dispatch of events into the implementations event
1624 * model. Events dispatched in this manner will have the same capturing and
1625 * bubbling behavior as events dispatched directly by the implementation. The
1626 * target of the event is any nodes in the subtree of the EventTarget on which
1627 * dispatchEvent is called.
1628 *
1629 * GDOME_UNSPECIFIED_EVENT_TYPE_ERR: Raised if the Event's type was not
1630 * specified by initializing the event before dispatchEvent was called.
1631 * Specification of the Event's type as %NULL or an empty string will also
1632 * trigger this exception.
1633 */
1634 void
gdome_xml_n_subTreeDispatchEvent(GdomeNode * self,GdomeEvent * evt,GdomeException * exc)1635 gdome_xml_n_subTreeDispatchEvent (GdomeNode *self, GdomeEvent *evt, GdomeException *exc)
1636 {
1637 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1638 GdomeNode *child, *temp;
1639
1640 g_return_if_fail (priv != NULL);
1641 g_return_if_fail (GDOME_XML_IS_N (priv));
1642 g_return_if_fail (evt != NULL);
1643 g_return_if_fail (exc != NULL);
1644
1645 child = gdome_xml_n_firstChild (self, exc);
1646
1647 while (child) {
1648 gdome_xml_n_dispatchEvent (child, evt, exc);
1649 gdome_xml_n_subTreeDispatchEvent (child, evt, exc);
1650 temp = gdome_xml_n_nextSibling (child, exc);
1651 gdome_xml_n_unref (child, exc);
1652 child = temp;
1653 }
1654 }
1655
1656 /**
1657 * gdome_xml_n_canAppend:
1658 * @self: Node Object ref
1659 * @newChild: The Node Object ref of the node to test
1660 * @exc: Exception Object ref
1661 *
1662 * Tests if a @newChild can be added in the child list of this node.
1663 * Returns: %TRUE if @newChild can be added, %FALSE otherwise.
1664 */
1665 GdomeBoolean
gdome_xml_n_canAppend(GdomeNode * self,GdomeNode * newChild,GdomeException * exc)1666 gdome_xml_n_canAppend (GdomeNode *self, GdomeNode *newChild, GdomeException *exc)
1667 {
1668 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1669 Gdome_xml_Node *new_priv = (Gdome_xml_Node *)newChild;
1670 xmlElementType new_type;
1671 GdomeBoolean ret = TRUE;
1672
1673 g_return_val_if_fail (priv != NULL, FALSE);
1674 g_return_val_if_fail (GDOME_XML_IS_N (priv), FALSE);
1675 g_return_val_if_fail (new_priv != NULL, FALSE);
1676 g_return_val_if_fail (GDOME_XML_IS_N (new_priv), FALSE);
1677 g_return_val_if_fail (exc != NULL, FALSE);
1678
1679 /* Check if self can have a child of newChild type */
1680 new_type = gdome_xmlGetType (new_priv->n);
1681 if (new_type == XML_DOCUMENT_FRAG_NODE)
1682 return TRUE;
1683 switch (gdome_xmlGetType (priv->n)) {
1684 case XML_DOCUMENT_TYPE_NODE:
1685 case XML_DTD_NODE:
1686 case XML_PI_NODE:
1687 case XML_COMMENT_NODE:
1688 case XML_TEXT_NODE:
1689 case XML_CDATA_SECTION_NODE:
1690 case XML_NOTATION_NODE:
1691 ret = FALSE;
1692 break;
1693 case XML_DOCUMENT_NODE:
1694 /* Element (max of one), ProcessingInstruction, Comment, DocumentType (max of one) */
1695 if ((new_type != XML_ELEMENT_NODE &&
1696 new_type != XML_PI_NODE &&
1697 new_type != XML_COMMENT_NODE &&
1698 new_type != XML_DTD_NODE &&
1699 new_type != XML_DOCUMENT_TYPE_NODE) ||
1700 (new_type == XML_ELEMENT_NODE &&
1701 xmlDocGetRootElement ((xmlDoc *)priv->n) != NULL) ||
1702 ((new_type == XML_DTD_NODE ||
1703 new_type == XML_DOCUMENT_TYPE_NODE) &&
1704 ((xmlDoc *)priv->n)->intSubset != NULL))
1705 ret = FALSE;
1706 break;
1707 case XML_DOCUMENT_FRAG_NODE:
1708 case XML_ENTITY_REF_NODE:
1709 case XML_ELEMENT_NODE:
1710 case XML_ENTITY_NODE:
1711 case XML_ENTITY_DECL:
1712 /* Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference */
1713 if (new_type != XML_ELEMENT_NODE &&
1714 new_type != XML_PI_NODE &&
1715 new_type != XML_COMMENT_NODE &&
1716 new_type != XML_TEXT_NODE &&
1717 new_type != XML_CDATA_SECTION_NODE &&
1718 new_type != XML_ENTITY_REF_NODE)
1719 ret = FALSE;
1720 break;
1721 case XML_ATTRIBUTE_NODE:
1722 /* Text, EntityReference */
1723 if (new_type != XML_TEXT_NODE &&
1724 new_type != XML_ENTITY_REF_NODE)
1725 ret = FALSE;
1726 break;
1727 default:
1728 g_warning ("gdome_xml_n_canAppend: invalid node type");
1729 ret = FALSE;
1730 break;
1731 }
1732
1733 /* Check if newChild is an ancestor of self */
1734 if (ret) {
1735 xmlNode *p = priv->n;
1736 while (p != NULL) {
1737 if (p == new_priv->n) {
1738 ret = FALSE;
1739 break;
1740 }
1741 p = gdome_xmlGetParent (p);
1742 }
1743 }
1744
1745 return ret;
1746 }
1747
1748 /**
1749 * gdome_xml_n_eventEnabledByCode:
1750 * @self: Node Objects ref
1751 * @code: The event type to check
1752 *
1753 * Returns: TRUE if the specified event type is enabled
1754 */
1755 GdomeBoolean
gdome_xml_n_eventEnabledByCode(GdomeNode * self,guint32 code)1756 gdome_xml_n_eventEnabledByCode (GdomeNode *self, guint32 code)
1757 {
1758 Gdome_xml_Node *priv = (Gdome_xml_Node *)self;
1759 GdomeException exc = 0;
1760 GdomeDocument *doc;
1761 GdomeBoolean res;
1762
1763 g_return_val_if_fail (priv != NULL, FALSE);
1764 g_return_val_if_fail (GDOME_XML_IS_N (priv), FALSE);
1765
1766 doc = gdome_xml_doc_mkref (gdome_xmlGetOwnerOrSelf (priv->n));
1767 g_assert(doc != NULL);
1768
1769 res = gdome_xml_doc_eventEnabledByCode (doc, code);
1770
1771 gdome_doc_unref(doc, &exc);
1772 g_assert(exc == 0);
1773
1774 return res;
1775 }
1776