xref: /PHP-8.0/ext/dom/element.c (revision 424c2654)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | http://www.php.net/license/3_01.txt                                  |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Authors: Christian Stocker <chregu@php.net>                          |
14    |          Rob Richards <rrichards@php.net>                            |
15    +----------------------------------------------------------------------+
16 */
17 
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 
22 #include "php.h"
23 #if defined(HAVE_LIBXML) && defined(HAVE_DOM)
24 #include "php_dom.h"
25 
26 /*
27 * class DOMElement extends DOMNode
28 *
29 * URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-745549614
30 * Since:
31 */
32 
33 /* {{{ */
PHP_METHOD(DOMElement,__construct)34 PHP_METHOD(DOMElement, __construct)
35 {
36 	xmlNodePtr nodep = NULL, oldnode = NULL;
37 	dom_object *intern;
38 	char *name, *value = NULL, *uri = NULL;
39 	char *localname = NULL, *prefix = NULL;
40 	int errorcode = 0;
41 	size_t name_len, value_len = 0, uri_len = 0;
42 	int name_valid;
43 	xmlNsPtr nsptr = NULL;
44 
45 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!s", &name, &name_len, &value, &value_len, &uri, &uri_len) == FAILURE) {
46 		RETURN_THROWS();
47 	}
48 
49 	name_valid = xmlValidateName((xmlChar *) name, 0);
50 	if (name_valid != 0) {
51 		php_dom_throw_error(INVALID_CHARACTER_ERR, 1);
52 		RETURN_THROWS();
53 	}
54 
55 	/* Namespace logic is separate and only when uri passed in to insure no BC breakage */
56 	if (uri_len > 0) {
57 		errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len);
58 		if (errorcode == 0) {
59 			nodep = xmlNewNode (NULL, (xmlChar *)localname);
60 			if (nodep != NULL && uri != NULL) {
61 				nsptr = dom_get_ns(nodep, uri, &errorcode, prefix);
62 				xmlSetNs(nodep, nsptr);
63 			}
64 		}
65 		xmlFree(localname);
66 		if (prefix != NULL) {
67 			xmlFree(prefix);
68 		}
69 		if (errorcode != 0) {
70 			if (nodep != NULL) {
71 				xmlFreeNode(nodep);
72 			}
73 			php_dom_throw_error(errorcode, 1);
74 			RETURN_THROWS();
75 		}
76 	} else {
77 	    /* If you don't pass a namespace uri, then you can't set a prefix */
78 	    localname = (char *) xmlSplitQName2((xmlChar *) name, (xmlChar **) &prefix);
79 	    if (prefix != NULL) {
80 			xmlFree(localname);
81 			xmlFree(prefix);
82 	        php_dom_throw_error(NAMESPACE_ERR, 1);
83 	        RETURN_THROWS();
84 	    }
85 		nodep = xmlNewNode(NULL, (xmlChar *) name);
86 	}
87 
88 	if (!nodep) {
89 		php_dom_throw_error(INVALID_STATE_ERR, 1);
90 		RETURN_THROWS();
91 	}
92 
93 	if (value_len > 0) {
94 		xmlNodeSetContentLen(nodep, (xmlChar *) value, value_len);
95 	}
96 
97 	intern = Z_DOMOBJ_P(ZEND_THIS);
98 	oldnode = dom_object_get_node(intern);
99 	if (oldnode != NULL) {
100 		php_libxml_node_free_resource(oldnode );
101 	}
102 	php_libxml_increment_node_ptr((php_libxml_node_object *)intern, nodep, (void *)intern);
103 }
104 /* }}} end DOMElement::__construct */
105 
106 /* {{{ tagName	string
107 readonly=yes
108 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-104682815
109 Since:
110 */
dom_element_tag_name_read(dom_object * obj,zval * retval)111 int dom_element_tag_name_read(dom_object *obj, zval *retval)
112 {
113 	xmlNodePtr nodep;
114 	xmlNsPtr ns;
115 	xmlChar *qname;
116 
117 	nodep = dom_object_get_node(obj);
118 
119 	if (nodep == NULL) {
120 		php_dom_throw_error(INVALID_STATE_ERR, 0);
121 		return FAILURE;
122 	}
123 
124 	ns = nodep->ns;
125 	if (ns != NULL && ns->prefix) {
126 		qname = xmlStrdup(ns->prefix);
127 		qname = xmlStrcat(qname, (xmlChar *)":");
128 		qname = xmlStrcat(qname, nodep->name);
129 		ZVAL_STRING(retval, (char *)qname);
130 		xmlFree(qname);
131 	} else {
132 		ZVAL_STRING(retval, (char *) nodep->name);
133 	}
134 
135 	return SUCCESS;
136 }
137 
138 /* }}} */
139 
140 /* {{{ schemaTypeInfo	typeinfo
141 readonly=yes
142 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Element-schemaTypeInfo
143 Since: DOM Level 3
144 */
dom_element_schema_type_info_read(dom_object * obj,zval * retval)145 int dom_element_schema_type_info_read(dom_object *obj, zval *retval)
146 {
147 	ZVAL_NULL(retval);
148 	return SUCCESS;
149 }
150 
151 /* }}} */
152 
dom_get_dom1_attribute(xmlNodePtr elem,xmlChar * name)153 static xmlNodePtr dom_get_dom1_attribute(xmlNodePtr elem, xmlChar *name) /* {{{ */
154 {
155     int len;
156     const xmlChar *nqname;
157 
158 	nqname = xmlSplitQName3(name, &len);
159 	if (nqname != NULL) {
160 		xmlNsPtr ns;
161 		xmlChar *prefix = xmlStrndup(name, len);
162 		if (prefix && xmlStrEqual(prefix, (xmlChar *)"xmlns")) {
163 			ns = elem->nsDef;
164 			while (ns) {
165 				if (xmlStrEqual(ns->prefix, nqname)) {
166 					break;
167 				}
168 				ns = ns->next;
169 			}
170 			xmlFree(prefix);
171 			return (xmlNodePtr)ns;
172 		}
173 		ns = xmlSearchNs(elem->doc, elem, prefix);
174 		if (prefix != NULL) {
175 			xmlFree(prefix);
176 		}
177 		if (ns != NULL) {
178 			return (xmlNodePtr)xmlHasNsProp(elem, nqname, ns->href);
179 		}
180 	} else {
181 		if (xmlStrEqual(name, (xmlChar *)"xmlns")) {
182 			xmlNsPtr nsPtr = elem->nsDef;
183 			while (nsPtr) {
184 				if (nsPtr->prefix == NULL) {
185 					return (xmlNodePtr)nsPtr;
186 				}
187 				nsPtr = nsPtr->next;
188 			}
189 			return NULL;
190 		}
191 	}
192 	return (xmlNodePtr)xmlHasNsProp(elem, name, NULL);
193 }
194 /* }}} */
195 
196 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-666EE0F9
197 Since:
198 */
PHP_METHOD(DOMElement,getAttribute)199 PHP_METHOD(DOMElement, getAttribute)
200 {
201 	zval *id;
202 	xmlNode *nodep;
203 	char *name;
204 	xmlChar *value = NULL;
205 	dom_object *intern;
206 	xmlNodePtr attr;
207 	size_t name_len;
208 
209 	id = ZEND_THIS;
210 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
211 		RETURN_THROWS();
212 	}
213 
214 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
215 
216 	attr = dom_get_dom1_attribute(nodep, (xmlChar *)name);
217 	if (attr) {
218 		switch (attr->type) {
219 			case XML_ATTRIBUTE_NODE:
220 				value = xmlNodeListGetString(attr->doc, attr->children, 1);
221 				break;
222 			case XML_NAMESPACE_DECL:
223 				value = xmlStrdup(((xmlNsPtr)attr)->href);
224 				break;
225 			default:
226 				value = xmlStrdup(((xmlAttributePtr)attr)->defaultValue);
227 		}
228 	}
229 
230 	if (value == NULL) {
231 		RETURN_EMPTY_STRING();
232 	} else {
233 		RETVAL_STRING((char *)value);
234 		xmlFree(value);
235 	}
236 }
237 /* }}} end dom_element_get_attribute */
238 
239 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68F082
240 Since:
241 */
PHP_METHOD(DOMElement,setAttribute)242 PHP_METHOD(DOMElement, setAttribute)
243 {
244 	zval *id;
245 	xmlNode *nodep;
246 	xmlNodePtr attr = NULL;
247 	int ret, name_valid;
248 	size_t name_len, value_len;
249 	dom_object *intern;
250 	char *name, *value;
251 
252 	id = ZEND_THIS;
253 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &name, &name_len, &value, &value_len) == FAILURE) {
254 		RETURN_THROWS();
255 	}
256 
257 	if (name_len == 0) {
258 		zend_argument_value_error(1, "cannot be empty");
259 		RETURN_THROWS();
260 	}
261 
262 	name_valid = xmlValidateName((xmlChar *) name, 0);
263 	if (name_valid != 0) {
264 		php_dom_throw_error(INVALID_CHARACTER_ERR, 1);
265 		RETURN_THROWS();
266 	}
267 
268 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
269 
270 	if (dom_node_is_read_only(nodep) == SUCCESS) {
271 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
272 		RETURN_FALSE;
273 	}
274 
275 	attr = dom_get_dom1_attribute(nodep, (xmlChar *)name);
276 	if (attr != NULL) {
277 		switch (attr->type) {
278 			case XML_ATTRIBUTE_NODE:
279 				node_list_unlink(attr->children);
280 				break;
281 			case XML_NAMESPACE_DECL:
282 				RETURN_FALSE;
283 			default:
284 				break;
285 		}
286 
287 	}
288 
289 	if (xmlStrEqual((xmlChar *)name, (xmlChar *)"xmlns")) {
290 		if (xmlNewNs(nodep, (xmlChar *)value, NULL)) {
291 			RETURN_TRUE;
292 		}
293 	} else {
294 		attr = (xmlNodePtr)xmlSetProp(nodep, (xmlChar *) name, (xmlChar *)value);
295 	}
296 	if (!attr) {
297 		zend_argument_value_error(1, "must be a valid XML attribute");
298 		RETURN_THROWS();
299 	}
300 
301 	DOM_RET_OBJ(attr, &ret, intern);
302 
303 }
304 /* }}} end dom_element_set_attribute */
305 
306 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6D6AC0F9
307 Since:
308 */
PHP_METHOD(DOMElement,removeAttribute)309 PHP_METHOD(DOMElement, removeAttribute)
310 {
311 	zval *id;
312 	xmlNodePtr nodep, attrp;
313 	dom_object *intern;
314 	size_t name_len;
315 	char *name;
316 
317 	id = ZEND_THIS;
318 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
319 		RETURN_THROWS();
320 	}
321 
322 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
323 
324 	if (dom_node_is_read_only(nodep) == SUCCESS) {
325 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
326 		RETURN_FALSE;
327 	}
328 
329 	attrp = dom_get_dom1_attribute(nodep, (xmlChar *)name);
330 	if (attrp == NULL) {
331 		RETURN_FALSE;
332 	}
333 
334 	switch (attrp->type) {
335 		case XML_ATTRIBUTE_NODE:
336 			if (php_dom_object_get_data(attrp) == NULL) {
337 			node_list_unlink(attrp->children);
338 				xmlUnlinkNode(attrp);
339 				xmlFreeProp((xmlAttrPtr)attrp);
340 		} else {
341 				xmlUnlinkNode(attrp);
342 		}
343 			break;
344 		case XML_NAMESPACE_DECL:
345 			RETURN_FALSE;
346 		default:
347 			break;
348 	}
349 
350 	RETURN_TRUE;
351 }
352 /* }}} end dom_element_remove_attribute */
353 
354 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-217A91B8
355 Since:
356 */
PHP_METHOD(DOMElement,getAttributeNode)357 PHP_METHOD(DOMElement, getAttributeNode)
358 {
359 	zval *id;
360 	xmlNodePtr nodep, attrp;
361 	size_t name_len;
362 	int ret;
363 	dom_object *intern;
364 	char *name;
365 
366 	id = ZEND_THIS;
367 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
368 		RETURN_THROWS();
369 	}
370 
371 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
372 
373 	attrp = dom_get_dom1_attribute(nodep, (xmlChar *)name);
374 	if (attrp == NULL) {
375 		RETURN_FALSE;
376 	}
377 
378 	if (attrp->type == XML_NAMESPACE_DECL) {
379 		xmlNsPtr curns;
380 		xmlNodePtr nsparent;
381 
382 		nsparent = attrp->_private;
383 		curns = xmlNewNs(NULL, attrp->name, NULL);
384 		if (attrp->children) {
385 			curns->prefix = xmlStrdup((xmlChar *) attrp->children);
386 		}
387 		if (attrp->children) {
388 			attrp = xmlNewDocNode(nodep->doc, NULL, (xmlChar *) attrp->children, attrp->name);
389 		} else {
390 			attrp = xmlNewDocNode(nodep->doc, NULL, (xmlChar *)"xmlns", attrp->name);
391 		}
392 		attrp->type = XML_NAMESPACE_DECL;
393 		attrp->parent = nsparent;
394 		attrp->ns = curns;
395 	}
396 
397 	DOM_RET_OBJ((xmlNodePtr) attrp, &ret, intern);
398 }
399 /* }}} end dom_element_get_attribute_node */
400 
401 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-887236154
402 Since:
403 */
PHP_METHOD(DOMElement,setAttributeNode)404 PHP_METHOD(DOMElement, setAttributeNode)
405 {
406 	zval *id, *node;
407 	xmlNode *nodep;
408 	xmlAttr *attrp, *existattrp = NULL;
409 	dom_object *intern, *attrobj, *oldobj;
410 	int ret;
411 
412 	id = ZEND_THIS;
413 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &node, dom_attr_class_entry) == FAILURE) {
414 		RETURN_THROWS();
415 	}
416 
417 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
418 
419 	if (dom_node_is_read_only(nodep) == SUCCESS) {
420 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
421 		RETURN_FALSE;
422 	}
423 
424 	DOM_GET_OBJ(attrp, node, xmlAttrPtr, attrobj);
425 
426 	if (attrp->type != XML_ATTRIBUTE_NODE) {
427 		zend_argument_value_error(1, "must have the node attribute");
428 		RETURN_THROWS();
429 	}
430 
431 	if (!(attrp->doc == NULL || attrp->doc == nodep->doc)) {
432 		php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document));
433 		RETURN_FALSE;
434 	}
435 
436 	existattrp = xmlHasProp(nodep, attrp->name);
437 	if (existattrp != NULL && existattrp->type != XML_ATTRIBUTE_DECL) {
438 		if ((oldobj = php_dom_object_get_data((xmlNodePtr) existattrp)) != NULL &&
439 			((php_libxml_node_ptr *)oldobj->ptr)->node == (xmlNodePtr) attrp)
440 		{
441 			RETURN_NULL();
442 		}
443 		xmlUnlinkNode((xmlNodePtr) existattrp);
444 	}
445 
446 	if (attrp->parent != NULL) {
447 		xmlUnlinkNode((xmlNodePtr) attrp);
448 	}
449 
450 	if (attrp->doc == NULL && nodep->doc != NULL) {
451 		attrobj->document = intern->document;
452 		php_libxml_increment_doc_ref((php_libxml_node_object *)attrobj, NULL);
453 	}
454 
455 	xmlAddChild(nodep, (xmlNodePtr) attrp);
456 
457 	/* Returns old property if removed otherwise NULL */
458 	if (existattrp != NULL) {
459 		DOM_RET_OBJ((xmlNodePtr) existattrp, &ret, intern);
460 	} else {
461 		RETVAL_NULL();
462 	}
463 
464 }
465 /* }}} end dom_element_set_attribute_node */
466 
467 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D589198
468 Since:
469 */
PHP_METHOD(DOMElement,removeAttributeNode)470 PHP_METHOD(DOMElement, removeAttributeNode)
471 {
472 	zval *id, *node;
473 	xmlNode *nodep;
474 	xmlAttr *attrp;
475 	dom_object *intern, *attrobj;
476 	int ret;
477 
478 	id = ZEND_THIS;
479 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &node, dom_attr_class_entry) == FAILURE) {
480 		RETURN_THROWS();
481 	}
482 
483 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
484 
485 	if (dom_node_is_read_only(nodep) == SUCCESS) {
486 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
487 		RETURN_FALSE;
488 	}
489 
490 	DOM_GET_OBJ(attrp, node, xmlAttrPtr, attrobj);
491 
492 	if (attrp->type != XML_ATTRIBUTE_NODE || attrp->parent != nodep) {
493 		php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document));
494 		RETURN_FALSE;
495 	}
496 
497 	xmlUnlinkNode((xmlNodePtr) attrp);
498 
499 	DOM_RET_OBJ((xmlNodePtr) attrp, &ret, intern);
500 
501 }
502 /* }}} end dom_element_remove_attribute_node */
503 
504 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1938918D
505 Since:
506 */
PHP_METHOD(DOMElement,getElementsByTagName)507 PHP_METHOD(DOMElement, getElementsByTagName)
508 {
509 	zval *id;
510 	xmlNodePtr elemp;
511 	size_t name_len;
512 	dom_object *intern, *namednode;
513 	char *name;
514 	xmlChar *local;
515 
516 	id = ZEND_THIS;
517 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
518 		RETURN_THROWS();
519 	}
520 
521 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
522 
523 	php_dom_create_iterator(return_value, DOM_NODELIST);
524 	namednode = Z_DOMOBJ_P(return_value);
525 	local = xmlCharStrndup(name, name_len);
526 	dom_namednode_iter(intern, 0, namednode, NULL, local, NULL);
527 }
528 /* }}} end dom_element_get_elements_by_tag_name */
529 
530 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElGetAttrNS
531 Since: DOM Level 2
532 */
PHP_METHOD(DOMElement,getAttributeNS)533 PHP_METHOD(DOMElement, getAttributeNS)
534 {
535 	zval *id;
536 	xmlNodePtr elemp;
537 	xmlNsPtr nsptr;
538 	dom_object *intern;
539 	size_t uri_len = 0, name_len = 0;
540 	char *uri, *name;
541 	xmlChar *strattr;
542 
543 	id = ZEND_THIS;
544 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
545 		RETURN_THROWS();
546 	}
547 
548 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
549 
550 	strattr = xmlGetNsProp(elemp, (xmlChar *) name, (xmlChar *) uri);
551 
552 	if (strattr != NULL) {
553 		RETVAL_STRING((char *)strattr);
554 		xmlFree(strattr);
555 	} else {
556 		if (xmlStrEqual((xmlChar *) uri, (xmlChar *)DOM_XMLNS_NAMESPACE)) {
557 			nsptr = dom_get_nsdecl(elemp, (xmlChar *)name);
558 			if (nsptr != NULL) {
559 				RETVAL_STRING((char *) nsptr->href);
560 			} else {
561 				RETVAL_EMPTY_STRING();
562 			}
563 		} else {
564 			RETVAL_EMPTY_STRING();
565 		}
566 	}
567 
568 }
569 /* }}} end dom_element_get_attribute_ns */
570 
_dom_new_reconNs(xmlDocPtr doc,xmlNodePtr tree,xmlNsPtr ns)571 static xmlNsPtr _dom_new_reconNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) /* {{{ */
572 {
573     xmlNsPtr def;
574     xmlChar prefix[50];
575     int counter = 1;
576 
577 	if ((tree == NULL) || (ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) {
578 		return NULL;
579 	}
580 
581 	/* Code taken from libxml2 (2.6.20) xmlNewReconciliedNs
582 	 *
583 	 * Find a close prefix which is not already in use.
584 	 * Let's strip namespace prefixes longer than 20 chars !
585 	 */
586 	if (ns->prefix == NULL)
587 		snprintf((char *) prefix, sizeof(prefix), "default");
588 	else
589 		snprintf((char *) prefix, sizeof(prefix), "%.20s", (char *)ns->prefix);
590 
591 	def = xmlSearchNs(doc, tree, prefix);
592 	while (def != NULL) {
593 		if (counter > 1000) return(NULL);
594 		if (ns->prefix == NULL)
595 			snprintf((char *) prefix, sizeof(prefix), "default%d", counter++);
596 		else
597 			snprintf((char *) prefix, sizeof(prefix), "%.20s%d",
598 			(char *)ns->prefix, counter++);
599 		def = xmlSearchNs(doc, tree, prefix);
600 	}
601 
602 	/*
603 	 * OK, now we are ready to create a new one.
604 	 */
605 	def = xmlNewNs(tree, ns->href, prefix);
606 	return(def);
607 }
608 /* }}} */
609 
610 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetAttrNS
611 Since: DOM Level 2
612 */
PHP_METHOD(DOMElement,setAttributeNS)613 PHP_METHOD(DOMElement, setAttributeNS)
614 {
615 	zval *id;
616 	xmlNodePtr elemp, nodep = NULL;
617 	xmlNsPtr nsptr;
618 	xmlAttr *attr;
619 	size_t uri_len = 0, name_len = 0, value_len = 0;
620 	char *uri, *name, *value;
621 	char *localname = NULL, *prefix = NULL;
622 	dom_object *intern;
623 	int errorcode = 0, stricterror, is_xmlns = 0, name_valid;
624 
625 	id = ZEND_THIS;
626 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!ss", &uri, &uri_len, &name, &name_len, &value, &value_len) == FAILURE) {
627 		RETURN_THROWS();
628 	}
629 
630 	if (name_len == 0) {
631 		zend_argument_value_error(2, "cannot be empty");
632 		RETURN_THROWS();
633 	}
634 
635 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
636 
637 	stricterror = dom_get_strict_error(intern->document);
638 
639 	if (dom_node_is_read_only(elemp) == SUCCESS) {
640 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
641 		RETURN_NULL();
642 	}
643 
644 	errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len);
645 
646 	if (errorcode == 0) {
647 		if (uri_len > 0) {
648 			nodep = (xmlNodePtr) xmlHasNsProp(elemp, (xmlChar *) localname, (xmlChar *) uri);
649 			if (nodep != NULL && nodep->type != XML_ATTRIBUTE_DECL) {
650 				node_list_unlink(nodep->children);
651 			}
652 
653 			if ((xmlStrEqual((xmlChar *) prefix, (xmlChar *)"xmlns") ||
654 				(prefix == NULL && xmlStrEqual((xmlChar *) localname, (xmlChar *)"xmlns"))) &&
655 				xmlStrEqual((xmlChar *) uri, (xmlChar *)DOM_XMLNS_NAMESPACE)) {
656 				is_xmlns = 1;
657 				if (prefix == NULL) {
658 					nsptr = dom_get_nsdecl(elemp, NULL);
659 				} else {
660 					nsptr = dom_get_nsdecl(elemp, (xmlChar *)localname);
661 				}
662 			} else {
663 				nsptr = xmlSearchNsByHref(elemp->doc, elemp, (xmlChar *)uri);
664 				if (nsptr && nsptr->prefix == NULL) {
665 					xmlNsPtr tmpnsptr;
666 
667 					tmpnsptr = nsptr->next;
668 					while (tmpnsptr) {
669 						if ((tmpnsptr->prefix != NULL) && (tmpnsptr->href != NULL) &&
670 							(xmlStrEqual(tmpnsptr->href, (xmlChar *) uri))) {
671 							nsptr = tmpnsptr;
672 							break;
673 						}
674 						tmpnsptr = tmpnsptr->next;
675 					}
676 					if (tmpnsptr == NULL) {
677 						nsptr = _dom_new_reconNs(elemp->doc, elemp, nsptr);
678 					}
679 				}
680 			}
681 
682 			if (nsptr == NULL) {
683 				if (prefix == NULL) {
684 					if (is_xmlns == 1) {
685 						xmlNewNs(elemp, (xmlChar *)value, NULL);
686 						xmlReconciliateNs(elemp->doc, elemp);
687 					} else {
688 						errorcode = NAMESPACE_ERR;
689 					}
690 				} else {
691 					if (is_xmlns == 1) {
692 						xmlNewNs(elemp, (xmlChar *)value, (xmlChar *)localname);
693 					} else {
694 						nsptr = dom_get_ns(elemp, uri, &errorcode, prefix);
695 					}
696 					xmlReconciliateNs(elemp->doc, elemp);
697 				}
698 			} else {
699 				if (is_xmlns == 1) {
700 					if (nsptr->href) {
701 						xmlFree((xmlChar *) nsptr->href);
702 					}
703 					nsptr->href = xmlStrdup((xmlChar *)value);
704 				}
705 			}
706 
707 			if (errorcode == 0 && is_xmlns == 0) {
708 				xmlSetNsProp(elemp, nsptr, (xmlChar *)localname, (xmlChar *)value);
709 			}
710 		} else {
711 			name_valid = xmlValidateName((xmlChar *) localname, 0);
712 			if (name_valid != 0) {
713 				errorcode = INVALID_CHARACTER_ERR;
714 				stricterror = 1;
715 			} else {
716 				attr = xmlHasProp(elemp, (xmlChar *)localname);
717 				if (attr != NULL && attr->type != XML_ATTRIBUTE_DECL) {
718 					node_list_unlink(attr->children);
719 				}
720 				xmlSetProp(elemp, (xmlChar *)localname, (xmlChar *)value);
721 			}
722 		}
723 	}
724 
725 	xmlFree(localname);
726 	if (prefix != NULL) {
727 		xmlFree(prefix);
728 	}
729 
730 	if (errorcode != 0) {
731 		php_dom_throw_error(errorcode, stricterror);
732 	}
733 
734 	RETURN_NULL();
735 }
736 /* }}} end dom_element_set_attribute_ns */
737 
738 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElRemAtNS
739 Since: DOM Level 2
740 */
PHP_METHOD(DOMElement,removeAttributeNS)741 PHP_METHOD(DOMElement, removeAttributeNS)
742 {
743 	zval *id;
744 	xmlNode *nodep;
745 	xmlAttr *attrp;
746 	xmlNsPtr nsptr;
747 	dom_object *intern;
748 	size_t name_len, uri_len;
749 	char *name, *uri;
750 
751 	id = ZEND_THIS;
752 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
753 		RETURN_THROWS();
754 	}
755 
756 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
757 
758 	if (dom_node_is_read_only(nodep) == SUCCESS) {
759 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
760 		RETURN_NULL();
761 	}
762 
763 	attrp = xmlHasNsProp(nodep, (xmlChar *)name, (xmlChar *)uri);
764 
765 	nsptr = dom_get_nsdecl(nodep, (xmlChar *)name);
766 	if (nsptr != NULL) {
767 		if (xmlStrEqual((xmlChar *)uri, nsptr->href)) {
768 			if (nsptr->href != NULL) {
769 				xmlFree((char *) nsptr->href);
770 				nsptr->href = NULL;
771 			}
772 			if (nsptr->prefix != NULL) {
773 				xmlFree((char *) nsptr->prefix);
774 				nsptr->prefix = NULL;
775 			}
776 		} else {
777 			RETURN_NULL();
778 		}
779 	}
780 
781 	if (attrp && attrp->type != XML_ATTRIBUTE_DECL) {
782 		if (php_dom_object_get_data((xmlNodePtr) attrp) == NULL) {
783 			node_list_unlink(attrp->children);
784 			xmlUnlinkNode((xmlNodePtr) attrp);
785 			xmlFreeProp(attrp);
786 		} else {
787 			xmlUnlinkNode((xmlNodePtr) attrp);
788 		}
789 	}
790 
791 	RETURN_NULL();
792 }
793 /* }}} end dom_element_remove_attribute_ns */
794 
795 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElGetAtNodeNS
796 Since: DOM Level 2
797 */
PHP_METHOD(DOMElement,getAttributeNodeNS)798 PHP_METHOD(DOMElement, getAttributeNodeNS)
799 {
800 	zval *id;
801 	xmlNodePtr elemp, fakeAttrp;
802 	xmlAttrPtr attrp;
803 	dom_object *intern;
804 	size_t uri_len, name_len;
805 	int ret;
806 	char *uri, *name;
807 
808 	id = ZEND_THIS;
809 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
810 		RETURN_THROWS();
811 	}
812 
813 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
814 
815 	attrp = xmlHasNsProp(elemp, (xmlChar *)name, (xmlChar *)uri);
816 
817 	if (attrp == NULL) {
818 		if (xmlStrEqual((xmlChar *) uri, (xmlChar *)DOM_XMLNS_NAMESPACE)) {
819 			xmlNsPtr nsptr;
820 			nsptr = dom_get_nsdecl(elemp, (xmlChar *)name);
821 			if (nsptr != NULL) {
822 				xmlNsPtr curns;
823 				curns = xmlNewNs(NULL, nsptr->href, NULL);
824 				if (nsptr->prefix) {
825 					curns->prefix = xmlStrdup((xmlChar *) nsptr->prefix);
826 				}
827 				if (nsptr->prefix) {
828 					fakeAttrp = xmlNewDocNode(elemp->doc, NULL, (xmlChar *) nsptr->prefix, nsptr->href);
829 				} else {
830 					fakeAttrp = xmlNewDocNode(elemp->doc, NULL, (xmlChar *)"xmlns", nsptr->href);
831 				}
832 				fakeAttrp->type = XML_NAMESPACE_DECL;
833 				fakeAttrp->parent = elemp;
834 				fakeAttrp->ns = curns;
835 
836 				DOM_RET_OBJ(fakeAttrp, &ret, intern);
837 			} else {
838 				RETURN_NULL();
839 			}
840 		} else {
841 		   RETURN_NULL();
842 		}
843 	} else {
844 		DOM_RET_OBJ((xmlNodePtr) attrp, &ret, intern);
845 	}
846 
847 }
848 /* }}} end dom_element_get_attribute_node_ns */
849 
850 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetAtNodeNS
851 Since: DOM Level 2
852 */
PHP_METHOD(DOMElement,setAttributeNodeNS)853 PHP_METHOD(DOMElement, setAttributeNodeNS)
854 {
855 	zval *id, *node;
856 	xmlNode *nodep;
857 	xmlNs *nsp;
858 	xmlAttr *attrp, *existattrp = NULL;
859 	dom_object *intern, *attrobj, *oldobj;
860 	int ret;
861 
862 	id = ZEND_THIS;
863 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &node, dom_attr_class_entry) == FAILURE) {
864 		RETURN_THROWS();
865 	}
866 
867 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
868 
869 	if (dom_node_is_read_only(nodep) == SUCCESS) {
870 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
871 		RETURN_FALSE;
872 	}
873 
874 	DOM_GET_OBJ(attrp, node, xmlAttrPtr, attrobj);
875 
876 	/* ZPP Guarantees that a DOMAttr class is given, as it is converted to a xmlAttr
877 	 * to pass to libxml (see http://www.xmlsoft.org/html/libxml-tree.html#xmlAttr)
878 	 * if it is not of type XML_ATTRIBUTE_NODE it indicates a bug somewhere */
879 	ZEND_ASSERT(attrp->type == XML_ATTRIBUTE_NODE);
880 
881 	if (!(attrp->doc == NULL || attrp->doc == nodep->doc)) {
882 		php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document));
883 		RETURN_FALSE;
884 	}
885 
886     nsp = attrp->ns;
887     if (nsp != NULL) {
888         existattrp = xmlHasNsProp(nodep, nsp->href, attrp->name);
889     } else {
890         existattrp = xmlHasProp(nodep, attrp->name);
891     }
892 
893 	if (existattrp != NULL && existattrp->type != XML_ATTRIBUTE_DECL) {
894 		if ((oldobj = php_dom_object_get_data((xmlNodePtr) existattrp)) != NULL &&
895 			((php_libxml_node_ptr *)oldobj->ptr)->node == (xmlNodePtr) attrp)
896 		{
897 			RETURN_NULL();
898 		}
899 		xmlUnlinkNode((xmlNodePtr) existattrp);
900 	}
901 
902 	if (attrp->parent != NULL) {
903 		xmlUnlinkNode((xmlNodePtr) attrp);
904 	}
905 
906 	if (attrp->doc == NULL && nodep->doc != NULL) {
907 		attrobj->document = intern->document;
908 		php_libxml_increment_doc_ref((php_libxml_node_object *)attrobj, NULL);
909 	}
910 
911 	xmlAddChild(nodep, (xmlNodePtr) attrp);
912 
913 	/* Returns old property if removed otherwise NULL */
914 	if (existattrp != NULL) {
915 		DOM_RET_OBJ((xmlNodePtr) existattrp, &ret, intern);
916 	} else {
917 		RETVAL_NULL();
918 	}
919 
920 }
921 /* }}} end dom_element_set_attribute_node_ns */
922 
923 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-A6C90942
924 Since: DOM Level 2
925 */
PHP_METHOD(DOMElement,getElementsByTagNameNS)926 PHP_METHOD(DOMElement, getElementsByTagNameNS)
927 {
928 	zval *id;
929 	xmlNodePtr elemp;
930 	size_t uri_len, name_len;
931 	dom_object *intern, *namednode;
932 	char *uri, *name;
933 	xmlChar *local, *nsuri;
934 
935 	id = ZEND_THIS;
936 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
937 		RETURN_THROWS();
938 	}
939 
940 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
941 
942 	php_dom_create_iterator(return_value, DOM_NODELIST);
943 	namednode = Z_DOMOBJ_P(return_value);
944 	local = xmlCharStrndup(name, name_len);
945 	nsuri = xmlCharStrndup(uri ? uri : "", uri_len);
946 	dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri);
947 
948 }
949 /* }}} end dom_element_get_elements_by_tag_name_ns */
950 
951 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElHasAttr
952 Since: DOM Level 2
953 */
PHP_METHOD(DOMElement,hasAttribute)954 PHP_METHOD(DOMElement, hasAttribute)
955 {
956 	zval *id;
957 	xmlNode *nodep;
958 	dom_object *intern;
959 	char *name;
960 	size_t name_len;
961 	xmlNodePtr attr;
962 
963 	id = ZEND_THIS;
964 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
965 		RETURN_THROWS();
966 	}
967 
968 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
969 
970 	attr = dom_get_dom1_attribute(nodep, (xmlChar *)name);
971 	if (attr == NULL) {
972 		RETURN_FALSE;
973 	} else {
974 		RETURN_TRUE;
975 	}
976 }
977 /* }}} end dom_element_has_attribute */
978 
979 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElHasAttrNS
980 Since: DOM Level 2
981 */
PHP_METHOD(DOMElement,hasAttributeNS)982 PHP_METHOD(DOMElement, hasAttributeNS)
983 {
984 	zval *id;
985 	xmlNodePtr elemp;
986 	xmlNs *nsp;
987 	dom_object *intern;
988 	size_t uri_len, name_len;
989 	char *uri, *name;
990 	xmlChar *value;
991 
992 	id = ZEND_THIS;
993 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
994 		RETURN_THROWS();
995 	}
996 
997 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
998 
999 	value = xmlGetNsProp(elemp, (xmlChar *)name, (xmlChar *)uri);
1000 
1001 	if (value != NULL) {
1002 		xmlFree(value);
1003 		RETURN_TRUE;
1004 	} else {
1005 		if (xmlStrEqual((xmlChar *)uri, (xmlChar *)DOM_XMLNS_NAMESPACE)) {
1006 			nsp = dom_get_nsdecl(elemp, (xmlChar *)name);
1007 			if (nsp != NULL) {
1008 				RETURN_TRUE;
1009 			}
1010 		}
1011 	}
1012 
1013 	RETURN_FALSE;
1014 }
1015 /* }}} end dom_element_has_attribute_ns */
1016 
php_set_attribute_id(xmlAttrPtr attrp,zend_bool is_id)1017 static void php_set_attribute_id(xmlAttrPtr attrp, zend_bool is_id) /* {{{ */
1018 {
1019 	if (is_id == 1 && attrp->atype != XML_ATTRIBUTE_ID) {
1020 		xmlChar *id_val;
1021 
1022 		id_val = xmlNodeListGetString(attrp->doc, attrp->children, 1);
1023 		if (id_val != NULL) {
1024 			xmlAddID(NULL, attrp->doc, id_val, attrp);
1025 			xmlFree(id_val);
1026 		}
1027 	} else if (is_id == 0 && attrp->atype == XML_ATTRIBUTE_ID) {
1028 		xmlRemoveID(attrp->doc, attrp);
1029 		attrp->atype = 0;
1030 	}
1031 }
1032 /* }}} */
1033 
1034 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetIdAttr
1035 Since: DOM Level 3
1036 */
PHP_METHOD(DOMElement,setIdAttribute)1037 PHP_METHOD(DOMElement, setIdAttribute)
1038 {
1039 	zval *id;
1040 	xmlNode *nodep;
1041 	xmlAttrPtr attrp;
1042 	dom_object *intern;
1043 	char *name;
1044 	size_t name_len;
1045 	zend_bool is_id;
1046 
1047 	id = ZEND_THIS;
1048 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "sb", &name, &name_len, &is_id) == FAILURE) {
1049 		RETURN_THROWS();
1050 	}
1051 
1052 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1053 
1054 	if (dom_node_is_read_only(nodep) == SUCCESS) {
1055 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
1056 		RETURN_NULL();
1057 	}
1058 
1059 	attrp = xmlHasNsProp(nodep, (xmlChar *)name, NULL);
1060 	if (attrp == NULL || attrp->type == XML_ATTRIBUTE_DECL) {
1061 		php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document));
1062 	} else {
1063 		php_set_attribute_id(attrp, is_id);
1064 	}
1065 
1066 	RETURN_NULL();
1067 }
1068 /* }}} end dom_element_set_id_attribute */
1069 
1070 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetIdAttrNS
1071 Since: DOM Level 3
1072 */
PHP_METHOD(DOMElement,setIdAttributeNS)1073 PHP_METHOD(DOMElement, setIdAttributeNS)
1074 {
1075 	zval *id;
1076 	xmlNodePtr elemp;
1077 	xmlAttrPtr attrp;
1078 	dom_object *intern;
1079 	size_t uri_len, name_len;
1080 	char *uri, *name;
1081 	zend_bool is_id;
1082 
1083 	id = ZEND_THIS;
1084 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssb", &uri, &uri_len, &name, &name_len, &is_id) == FAILURE) {
1085 		RETURN_THROWS();
1086 	}
1087 
1088 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
1089 
1090 	if (dom_node_is_read_only(elemp) == SUCCESS) {
1091 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
1092 		RETURN_NULL();
1093 	}
1094 
1095 	attrp = xmlHasNsProp(elemp, (xmlChar *)name, (xmlChar *)uri);
1096 	if (attrp == NULL || attrp->type == XML_ATTRIBUTE_DECL) {
1097 		php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document));
1098 	} else {
1099 		php_set_attribute_id(attrp, is_id);
1100 	}
1101 
1102 	RETURN_NULL();
1103 }
1104 /* }}} end dom_element_set_id_attribute_ns */
1105 
1106 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetIdAttrNode
1107 Since: DOM Level 3
1108 */
PHP_METHOD(DOMElement,setIdAttributeNode)1109 PHP_METHOD(DOMElement, setIdAttributeNode)
1110 {
1111 	zval *id, *node;
1112 	xmlNode *nodep;
1113 	xmlAttrPtr attrp;
1114 	dom_object *intern, *attrobj;
1115 	zend_bool is_id;
1116 
1117 	id = ZEND_THIS;
1118 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ob", &node, dom_attr_class_entry, &is_id) == FAILURE) {
1119 		RETURN_THROWS();
1120 	}
1121 
1122 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1123 
1124 	if (dom_node_is_read_only(nodep) == SUCCESS) {
1125 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
1126 		RETURN_NULL();
1127 	}
1128 
1129 	DOM_GET_OBJ(attrp, node, xmlAttrPtr, attrobj);
1130 
1131 	if (attrp->parent != nodep) {
1132 		php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document));
1133 	} else {
1134 		php_set_attribute_id(attrp, is_id);
1135 	}
1136 
1137 	RETURN_NULL();
1138 }
1139 /* }}} end dom_element_set_id_attribute_node */
1140 
1141 /* {{{ URL:
1142 Since:
1143 */
PHP_METHOD(DOMElement,remove)1144 PHP_METHOD(DOMElement, remove)
1145 {
1146 	zval *id;
1147 	xmlNodePtr child;
1148 	dom_object *intern;
1149 
1150 	if (zend_parse_parameters_none() == FAILURE) {
1151 		RETURN_THROWS();
1152 	}
1153 
1154 	id = ZEND_THIS;
1155 	DOM_GET_OBJ(child, id, xmlNodePtr, intern);
1156 
1157 	dom_child_node_remove(intern);
1158 }
1159 /* }}} end DOMElement::remove */
1160 
PHP_METHOD(DOMElement,after)1161 PHP_METHOD(DOMElement, after)
1162 {
1163 	int argc;
1164 	zval *args, *id;
1165 	dom_object *intern;
1166 	xmlNode *context;
1167 
1168 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
1169 		RETURN_THROWS();
1170 	}
1171 
1172 	id = ZEND_THIS;
1173 	DOM_GET_OBJ(context, id, xmlNodePtr, intern);
1174 
1175 	dom_parent_node_after(intern, args, argc);
1176 }
1177 
PHP_METHOD(DOMElement,before)1178 PHP_METHOD(DOMElement, before)
1179 {
1180 	int argc;
1181 	zval *args, *id;
1182 	dom_object *intern;
1183 	xmlNode *context;
1184 
1185 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
1186 		RETURN_THROWS();
1187 	}
1188 
1189 	id = ZEND_THIS;
1190 	DOM_GET_OBJ(context, id, xmlNodePtr, intern);
1191 
1192 	dom_parent_node_before(intern, args, argc);
1193 }
1194 
1195 /* {{{ URL: https://dom.spec.whatwg.org/#dom-parentnode-append
1196 Since: DOM Living Standard (DOM4)
1197 */
PHP_METHOD(DOMElement,append)1198 PHP_METHOD(DOMElement, append)
1199 {
1200 	int argc;
1201 	zval *args, *id;
1202 	dom_object *intern;
1203 	xmlNode *context;
1204 
1205 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
1206 		RETURN_THROWS();
1207 	}
1208 
1209 	id = ZEND_THIS;
1210 	DOM_GET_OBJ(context, id, xmlNodePtr, intern);
1211 
1212 	dom_parent_node_append(intern, args, argc);
1213 }
1214 /* }}} end DOMElement::append */
1215 
1216 /* {{{ URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
1217 Since: DOM Living Standard (DOM4)
1218 */
PHP_METHOD(DOMElement,prepend)1219 PHP_METHOD(DOMElement, prepend)
1220 {
1221 	int argc;
1222 	zval *args, *id;
1223 	dom_object *intern;
1224 	xmlNode *context;
1225 
1226 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
1227 		RETURN_THROWS();
1228 	}
1229 
1230 	id = ZEND_THIS;
1231 	DOM_GET_OBJ(context, id, xmlNodePtr, intern);
1232 
1233 	dom_parent_node_prepend(intern, args, argc);
1234 }
1235 /* }}} end DOMElement::prepend */
1236 
1237 /* {{{ URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
1238 Since: DOM Living Standard (DOM4)
1239 */
PHP_METHOD(DOMElement,replaceWith)1240 PHP_METHOD(DOMElement, replaceWith)
1241 {
1242 	int argc;
1243 	zval *args, *id;
1244 	dom_object *intern;
1245 	xmlNode *context;
1246 
1247 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
1248 		RETURN_THROWS();
1249 	}
1250 
1251 	id = ZEND_THIS;
1252 	DOM_GET_OBJ(context, id, xmlNodePtr, intern);
1253 
1254 	dom_parent_node_after(intern, args, argc);
1255 	dom_child_node_remove(intern);
1256 }
1257 /* }}} end DOMElement::prepend */
1258 
1259 #endif
1260