php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
simplexml.c
Go to the documentation of this file.
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 | https://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: Sterling Hughes <sterling@php.net> |
14 | Marcus Boerger <helly@php.net> |
15 | Rob Richards <rrichards@php.net> |
16 +----------------------------------------------------------------------+
17*/
18
19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
23#include "php.h"
24#if defined(HAVE_LIBXML) && defined(HAVE_SIMPLEXML)
25
26#include "ext/standard/info.h"
27#include "ext/standard/php_string.h" /* For php_trim() */
28#include "php_simplexml.h"
30#include "simplexml_arginfo.h"
31#include "zend_exceptions.h"
32#include "zend_interfaces.h"
34
37
39{
41}
42/* }}} */
43
44static php_sxe_object* php_sxe_object_new(zend_class_entry *ce, zend_function *fptr_count);
45static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe);
46static xmlNodePtr php_sxe_reset_iterator_no_clear_iter_data(php_sxe_object *sxe, int use_data);
47static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data);
48static void php_sxe_iterator_dtor(zend_object_iterator *iter);
49static zend_result php_sxe_iterator_valid(zend_object_iterator *iter);
50static zval *php_sxe_iterator_current_data(zend_object_iterator *iter);
51static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key);
52static void php_sxe_iterator_move_forward(zend_object_iterator *iter);
53static void php_sxe_iterator_rewind(zend_object_iterator *iter);
54static zend_result sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type);
55
56static void sxe_unlink_node(xmlNodePtr node)
57{
58 xmlUnlinkNode(node);
59 /* Only destroy the nodes if we have no objects using them anymore.
60 * Don't assume simplexml owns these. */
61 if (!node->_private) {
62 php_libxml_node_free_resource(node);
63 }
64}
65
66/* {{{ _node_as_zval() */
67static void node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE_ITER itertype, zend_string *name, zend_string *nsprefix, int isprefix)
68{
69 php_sxe_object *subnode;
70
71 subnode = php_sxe_object_new(sxe->zo.ce, sxe->fptr_count);
72 subnode->document = sxe->document;
73 subnode->document->refcount++;
74 subnode->iter.type = itertype;
75 if (name) {
76 subnode->iter.name = zend_string_copy(name);
77 }
78 if (nsprefix && *ZSTR_VAL(nsprefix)) {
79 subnode->iter.nsprefix = zend_string_copy(nsprefix);
80 subnode->iter.isprefix = isprefix;
81 }
82
83 php_libxml_increment_node_ptr((php_libxml_node_object *)subnode, node, NULL);
84
85 ZVAL_OBJ(value, &subnode->zo);
86}
87/* }}} */
88
89static void node_as_zval_str(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE_ITER itertype, const xmlChar *name, const xmlChar *nsprefix, int isprefix)
90{
91 zend_string *name_str = zend_string_init((const char *) name, strlen((const char *) name), false);
92 zend_string *ns_str = nsprefix ? zend_string_init((const char *) nsprefix, strlen((const char *) nsprefix), false) : NULL;
93 node_as_zval(sxe, node, value, itertype, name_str, ns_str, isprefix);
94 zend_string_release_ex(name_str, false);
95 if (ns_str) {
96 zend_string_release_ex(ns_str, false);
97 }
98}
99
100static xmlNodePtr php_sxe_get_first_node_non_destructive(php_sxe_object *sxe, xmlNodePtr node)
101{
102 if (sxe && sxe->iter.type != SXE_ITER_NONE) {
103 return php_sxe_reset_iterator_no_clear_iter_data(sxe, false);
104 } else {
105 return node;
106 }
107}
108
109static inline int match_ns(xmlNodePtr node, const zend_string *name, int prefix) /* {{{ */
110{
111 if (name == NULL && (node->ns == NULL || node->ns->prefix == NULL)) {
112 return 1;
113 }
114
115 if (node->ns && xmlStrEqual(prefix ? node->ns->prefix : node->ns->href, name ? BAD_CAST ZSTR_VAL(name) : NULL)) {
116 return 1;
117 }
118
119 return 0;
120}
121/* }}} */
122
123static xmlNodePtr sxe_get_element_by_offset(php_sxe_object *sxe, zend_long offset, xmlNodePtr node, zend_long *cnt) /* {{{ */
124{
125 zend_long nodendx = 0;
126
127 if (sxe->iter.type == SXE_ITER_NONE) {
128 if (offset == 0) {
129 if (cnt) {
130 *cnt = 0;
131 }
132 return node;
133 } else {
134 return NULL;
135 }
136 }
137 while (node && nodendx <= offset) {
138 if (node->type == XML_ELEMENT_NODE && match_ns(node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
139 if (sxe->iter.type == SXE_ITER_CHILD || (
140 sxe->iter.type == SXE_ITER_ELEMENT && xmlStrEqual(node->name, BAD_CAST ZSTR_VAL(sxe->iter.name)))) {
141 if (nodendx == offset) {
142 break;
143 }
144 nodendx++;
145 }
146 }
147 node = node->next;
148 }
149
150 if (cnt) {
151 *cnt = nodendx;
152 }
153
154 return node;
155}
156/* }}} */
157
158static xmlNodePtr sxe_find_element_by_name(php_sxe_object *sxe, xmlNodePtr node, const zend_string *name) /* {{{ */
159{
160 const xmlChar *raw_name = BAD_CAST ZSTR_VAL(name);
161 while (node) {
162 if (node->type == XML_ELEMENT_NODE && match_ns(node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
163 if (xmlStrEqual(node->name, raw_name)) {
164 return node;
165 }
166 }
167 node = node->next;
168 }
169 return NULL;
170} /* }}} */
171
172static xmlNodePtr sxe_get_element_by_name(php_sxe_object *sxe, xmlNodePtr node, char *name, SXE_ITER *type) /* {{{ */
173{
174 int orgtype;
175 xmlNodePtr orgnode = node;
176
177 if (sxe->iter.type != SXE_ITER_ATTRLIST)
178 {
179 orgtype = sxe->iter.type;
180 if (sxe->iter.type == SXE_ITER_NONE) {
181 sxe->iter.type = SXE_ITER_CHILD;
182 }
183 node = php_sxe_get_first_node_non_destructive(sxe, node);
184 sxe->iter.type = orgtype;
185 }
186
187 if (sxe->iter.type == SXE_ITER_ELEMENT) {
188 orgnode = sxe_find_element_by_name(sxe, node, sxe->iter.name);
189 if (!orgnode) {
190 return NULL;
191 }
192 node = orgnode->children;
193 }
194
195 while (node) {
196 if (node->type == XML_ELEMENT_NODE && match_ns(node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
197 if (xmlStrEqual(node->name, (xmlChar *)name)) {
199 return orgnode;
200 }
201 }
202 node = node->next;
203 }
204
205 return NULL;
206}
207/* }}} */
208
209/* {{{ sxe_prop_dim_read() */
210static zval *sxe_prop_dim_read(zend_object *object, zval *member, bool elements, bool attribs, int type, zval *rv)
211{
212 php_sxe_object *sxe;
214 xmlNodePtr node;
215 xmlAttrPtr attr = NULL;
216 zval tmp_zv;
217 int nodendx = 0;
218 int test = 0;
219
220 sxe = php_sxe_fetch_object(object);
221
222 if (!member) {
223 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
224 /* This happens when the user did: $sxe[]->foo = $value */
225 zend_throw_error(NULL, "Cannot create unnamed attribute");
226 return &EG(uninitialized_zval);
227 }
228 goto long_dim;
229 } else {
230 ZVAL_DEREF(member);
231 if (Z_TYPE_P(member) == IS_LONG) {
232 if (sxe->iter.type != SXE_ITER_ATTRLIST) {
233long_dim:
234 attribs = 0;
235 elements = 1;
236 }
237 name = NULL;
238 } else {
239 if (Z_TYPE_P(member) != IS_STRING) {
241 if (UNEXPECTED(!str)) {
242 return &EG(uninitialized_zval);
243 }
244 ZVAL_STR(&tmp_zv, str);
245 member = &tmp_zv;
246 }
247 name = Z_STR_P(member);
248 }
249 }
250
251 GET_NODE(sxe, node);
252
253 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
254 attribs = 1;
255 elements = 0;
256 node = php_sxe_get_first_node_non_destructive(sxe, node);
257 attr = (xmlAttrPtr)node;
258 test = sxe->iter.name != NULL;
259 } else if (sxe->iter.type != SXE_ITER_CHILD) {
260 node = php_sxe_get_first_node_non_destructive(sxe, node);
261 attr = node ? node->properties : NULL;
262 test = 0;
263 if (!member && node && node->parent &&
264 node->parent->type == XML_DOCUMENT_NODE) {
265 /* This happens when the user did: $sxe[]->foo = $value */
266 zend_throw_error(NULL, "Cannot create unnamed attribute");
267 return &EG(uninitialized_zval);
268 }
269 }
270
271 ZVAL_UNDEF(rv);
272
273 if (node) {
274 if (attribs) {
275 if (Z_TYPE_P(member) != IS_LONG || sxe->iter.type == SXE_ITER_ATTRLIST) {
276 if (Z_TYPE_P(member) == IS_LONG) {
277 while (attr && nodendx <= Z_LVAL_P(member)) {
278 if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && match_ns((xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
279 if (nodendx == Z_LVAL_P(member)) {
280 node_as_zval(sxe, (xmlNodePtr) attr, rv, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix);
281 break;
282 }
283 nodendx++;
284 }
285 attr = attr->next;
286 }
287 } else {
288 while (attr) {
289 if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(name)) && match_ns((xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
290 node_as_zval(sxe, (xmlNodePtr) attr, rv, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix);
291 break;
292 }
293 attr = attr->next;
294 }
295 }
296 }
297 }
298
299 if (elements) {
300 if (!sxe->node) {
301 php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, node, NULL);
302 }
303 if (!member || Z_TYPE_P(member) == IS_LONG) {
304 zend_long cnt = 0;
305 xmlNodePtr mynode = node;
306
307 if (sxe->iter.type == SXE_ITER_CHILD) {
308 node = php_sxe_get_first_node_non_destructive(sxe, node);
309 }
310 if (sxe->iter.type == SXE_ITER_NONE) {
311 if (member && Z_LVAL_P(member) > 0) {
312 php_error_docref(NULL, E_WARNING, "Cannot add element %s number " ZEND_LONG_FMT " when only 0 such elements exist", mynode->name, Z_LVAL_P(member));
313 }
314 } else if (member) {
315 node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, &cnt);
316 } else {
317 node = NULL;
318 }
319 if (node) {
320 node_as_zval(sxe, node, rv, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix);
321 } else if (type == BP_VAR_W || type == BP_VAR_RW) {
322 if (member && cnt < Z_LVAL_P(member)) {
323 php_error_docref(NULL, E_WARNING, "Cannot add element %s number " ZEND_LONG_FMT " when only " ZEND_LONG_FMT " such elements exist", mynode->name, Z_LVAL_P(member), cnt);
324 }
325 node = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, NULL);
326 node_as_zval(sxe, node, rv, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix);
327 }
328 } else {
329 /* In BP_VAR_IS mode only return a proper node if it actually exists. */
330 if (type != BP_VAR_IS || sxe_find_element_by_name(sxe, node->children, name)) {
331 node_as_zval(sxe, node, rv, SXE_ITER_ELEMENT, name, sxe->iter.nsprefix, sxe->iter.isprefix);
332 }
333 }
334 }
335 }
336
337 if (member == &tmp_zv) {
338 zval_ptr_dtor_str(&tmp_zv);
339 }
340
341 if (Z_ISUNDEF_P(rv)) {
342 ZVAL_NULL(rv);
343 }
344
345 return rv;
346}
347/* }}} */
348
349/* {{{ sxe_property_read() */
350static zval *sxe_property_read(zend_object *object, zend_string *name, int type, void **cache_slot, zval *rv)
351{
352 zval member;
353 ZVAL_STR(&member, name);
354 return sxe_prop_dim_read(object, &member, 1, 0, type, rv);
355}
356/* }}} */
357
358/* {{{ sxe_dimension_read() */
359static zval *sxe_dimension_read(zend_object *object, zval *offset, int type, zval *rv)
360{
361 return sxe_prop_dim_read(object, offset, 0, 1, type, rv);
362}
363/* }}} */
364
365/* {{{ change_node_zval() */
366static void change_node_zval(xmlNodePtr node, zend_string *value)
367{
368 xmlChar *buffer = xmlEncodeEntitiesReentrant(node->doc, (xmlChar *)ZSTR_VAL(value));
369 /* check for NULL buffer in case of memory error in xmlEncodeEntitiesReentrant */
370 if (buffer) {
371 xmlNodeSetContent(node, buffer);
372 xmlFree(buffer);
373 }
374}
375/* }}} */
376
377/* {{{ sxe_property_write() */
378static zval *sxe_prop_dim_write(zend_object *object, zval *member, zval *value, bool elements, bool attribs, xmlNodePtr *pnewnode)
379{
380 php_sxe_object *sxe;
381 xmlNodePtr node;
382 xmlNodePtr newnode = NULL;
383 xmlNodePtr mynode;
384 xmlNodePtr tempnode;
385 xmlAttrPtr attr = NULL;
386 int counter = 0;
387 int is_attr = 0;
388 int nodendx = 0;
389 int test = 0;
390 zend_long cnt = 0;
391 zval tmp_zv;
392 zend_string *trim_str;
393 zend_string *value_str = NULL;
394
395 sxe = php_sxe_fetch_object(object);
396
397 if (!member) {
398 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
399 /* This happens when the user did: $sxe[] = $value
400 * and could also be E_PARSE, but we use this only during parsing
401 * and this is during runtime.
402 */
403 zend_throw_error(NULL, "Cannot append to an attribute list");
404 return &EG(error_zval);
405 }
406 goto long_dim;
407 } else {
408 ZVAL_DEREF(member);
409 if (Z_TYPE_P(member) == IS_LONG) {
410 if (sxe->iter.type != SXE_ITER_ATTRLIST) {
411long_dim:
412 attribs = 0;
413 elements = 1;
414 }
415 } else {
416 if (Z_TYPE_P(member) != IS_STRING) {
417 trim_str = zval_try_get_string_func(member);
418 if (UNEXPECTED(!trim_str)) {
419 return &EG(error_zval);
420 }
421
422 ZVAL_STR(&tmp_zv, php_trim(trim_str, NULL, 0, 3));
423 zend_string_release_ex(trim_str, 0);
424 member = &tmp_zv;
425 }
426
427 if (!Z_STRLEN_P(member)) {
428 zend_value_error("Cannot create %s with an empty name", attribs ? "attribute" : "element");
429 if (member == &tmp_zv) {
430 zval_ptr_dtor_str(&tmp_zv);
431 }
432 return &EG(error_zval);
433 }
434 }
435 }
436
437 GET_NODE(sxe, node);
438
439 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
440 attribs = 1;
441 elements = 0;
442 node = php_sxe_get_first_node_non_destructive(sxe, node);
443 attr = (xmlAttrPtr)node;
444 test = sxe->iter.name != NULL;
445 } else if (sxe->iter.type != SXE_ITER_CHILD) {
446 mynode = node;
447 node = php_sxe_get_first_node_non_destructive(sxe, node);
448 attr = node ? node->properties : NULL;
449 test = 0;
450 if (!member && node && node->parent &&
451 node->parent->type == XML_DOCUMENT_NODE) {
452 /* This happens when the user did: $sxe[] = $value
453 * and could also be E_PARSE, but we use this only during parsing
454 * and this is during runtime.
455 */
456 zend_value_error("Cannot append to an attribute list");
457 return &EG(error_zval);
458 }
459 if (attribs && !node && sxe->iter.type == SXE_ITER_ELEMENT) {
460 node = xmlNewChild(mynode, mynode->ns, BAD_CAST ZSTR_VAL(sxe->iter.name), NULL);
461 attr = node->properties;
462 }
463 }
464
465 mynode = node;
466
467 if (value) {
468 switch (Z_TYPE_P(value)) {
469 case IS_LONG:
470 case IS_FALSE:
471 case IS_TRUE:
472 case IS_DOUBLE:
473 case IS_NULL:
474 case IS_STRING:
475 value_str = zval_get_string(value);
476 break;
477 case IS_OBJECT:
479 zval zval_copy;
480 zend_result rv = sxe_object_cast_ex(Z_OBJ_P(value), &zval_copy, IS_STRING);
483
484 value_str = Z_STR(zval_copy);
485 break;
486 }
488 default:
489 if (member == &tmp_zv) {
490 zval_ptr_dtor_str(&tmp_zv);
491 }
492 zend_type_error("It's not possible to assign a complex type to %s, %s given", attribs ? "attributes" : "properties", zend_zval_value_name(value));
493 return &EG(error_zval);
494 }
495 }
496
497 if (node) {
498 php_libxml_invalidate_node_list_cache_from_doc(node->doc);
499
500 if (attribs) {
501 if (Z_TYPE_P(member) == IS_LONG) {
502 while (attr && nodendx <= Z_LVAL_P(member)) {
503 if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && match_ns((xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
504 if (nodendx == Z_LVAL_P(member)) {
505 is_attr = 1;
506 ++counter;
507 break;
508 }
509 nodendx++;
510 }
511 attr = attr->next;
512 }
513 } else {
514 while (attr) {
515 if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && xmlStrEqual(attr->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns((xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
516 is_attr = 1;
517 ++counter;
518 break;
519 }
520 attr = attr->next;
521 }
522 }
523
524 }
525
526 if (elements) {
527 if (!member || Z_TYPE_P(member) == IS_LONG) {
528 if (node->type == XML_ATTRIBUTE_NODE) {
529 zend_throw_error(NULL, "Cannot create duplicate attribute");
530 if (value_str) {
531 zend_string_release(value_str);
532 }
533 return &EG(error_zval);
534 }
535
536 if (sxe->iter.type == SXE_ITER_NONE) {
537 newnode = node;
538 ++counter;
539 if (member && Z_LVAL_P(member) > 0) {
540 php_error_docref(NULL, E_WARNING, "Cannot add element %s number " ZEND_LONG_FMT " when only 0 such elements exist", mynode->name, Z_LVAL_P(member));
541 value = &EG(error_zval);
542 }
543 } else if (member) {
544 newnode = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, &cnt);
545 if (newnode) {
546 ++counter;
547 }
548 }
549 } else {
550 node = node->children;
551 while (node) {
552 SKIP_TEXT(node);
553
554 if (xmlStrEqual(node->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
555 newnode = node;
556 ++counter;
557 }
558
559next_iter:
560 node = node->next;
561 }
562 }
563 }
564
565 if (counter == 1) {
566 if (is_attr) {
567 newnode = (xmlNodePtr) attr;
568 }
569 if (value_str) {
570 while ((tempnode = (xmlNodePtr) newnode->children)) {
571 sxe_unlink_node(tempnode);
572 }
573 change_node_zval(newnode, value_str);
574 }
575 } else if (counter > 1) {
576 php_error_docref(NULL, E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)");
577 value = &EG(error_zval);
578 } else if (elements) {
579 if (!node) {
580 if (!member || Z_TYPE_P(member) == IS_LONG) {
581 newnode = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, value_str ? (xmlChar *)ZSTR_VAL(value_str) : NULL);
582 } else {
583 /* Note: we cannot set the namespace here unconditionally because the parent may be a document.
584 * Passing NULL will let libxml decide to either inherit the namespace or not set one at all,
585 * depending on whether the parent is an element. */
586 newnode = xmlNewTextChild(mynode, NULL, (xmlChar *)Z_STRVAL_P(member), value_str ? (xmlChar *)ZSTR_VAL(value_str) : NULL);
587 }
588 } else if (!member || Z_TYPE_P(member) == IS_LONG) {
589 if (member && cnt < Z_LVAL_P(member)) {
590 php_error_docref(NULL, E_WARNING, "Cannot add element %s number " ZEND_LONG_FMT " when only " ZEND_LONG_FMT " such elements exist", mynode->name, Z_LVAL_P(member), cnt);
591 }
592 newnode = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, value_str ? (xmlChar *)ZSTR_VAL(value_str) : NULL);
593 }
594 } else if (attribs) {
595 if (Z_TYPE_P(member) == IS_LONG) {
596 php_error_docref(NULL, E_WARNING, "Cannot change attribute number " ZEND_LONG_FMT " when only %d attributes exist", Z_LVAL_P(member), nodendx);
597 } else {
598 newnode = (xmlNodePtr)xmlNewProp(node, (xmlChar *)Z_STRVAL_P(member), value_str ? (xmlChar *)ZSTR_VAL(value_str) : NULL);
599 }
600 }
601 }
602
603 if (member == &tmp_zv) {
604 zval_ptr_dtor_str(&tmp_zv);
605 }
606 if (pnewnode) {
607 *pnewnode = newnode;
608 }
609 if (value_str) {
610 zend_string_release(value_str);
611 }
612 return value;
613}
614/* }}} */
615
616/* {{{ sxe_property_write() */
617static zval *sxe_property_write(zend_object *object, zend_string *name, zval *value, void **cache_slot)
618{
619 zval member;
620 ZVAL_STR(&member, name);
621 zval *retval = sxe_prop_dim_write(object, &member, value, 1, 0, NULL);
622 return retval == &EG(error_zval) ? &EG(uninitialized_zval) : retval;
623}
624/* }}} */
625
626/* {{{ sxe_dimension_write() */
627static void sxe_dimension_write(zend_object *object, zval *offset, zval *value)
628{
629 sxe_prop_dim_write(object, offset, value, 0, 1, NULL);
630}
631/* }}} */
632
633static zval *sxe_property_get_adr(zend_object *object, zend_string *zname, int fetch_type, void **cache_slot) /* {{{ */
634{
635 php_sxe_object *sxe;
636 xmlNodePtr node;
637 zval ret;
638 char *name;
640 zval member;
641
642 if (cache_slot) {
643 cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
644 }
645
646 sxe = php_sxe_fetch_object(object);
647 GET_NODE(sxe, node);
648 if (UNEXPECTED(!node)) {
649 return &EG(error_zval);
650 }
651 name = ZSTR_VAL(zname);
652 node = sxe_get_element_by_name(sxe, node, name, &type);
653 if (node) {
654 return NULL;
655 }
656 ZVAL_STR(&member, zname);
657 if (sxe_prop_dim_write(object, &member, NULL, 1, 0, &node) == &EG(error_zval)) {
658 return &EG(error_zval);
659 }
661
662 node_as_zval(sxe, node, &ret, type, NULL, sxe->iter.nsprefix, sxe->iter.isprefix);
663
664 if (!Z_ISUNDEF(sxe->tmp)) {
665 zval_ptr_dtor(&sxe->tmp);
666 }
667
668 ZVAL_COPY_VALUE(&sxe->tmp, &ret);
669
670 return &sxe->tmp;
671}
672/* }}} */
673
674/* {{{ sxe_prop_dim_exists() */
675static int sxe_prop_dim_exists(zend_object *object, zval *member, int check_empty, bool elements, bool attribs)
676{
677 php_sxe_object *sxe;
678 xmlNodePtr node;
679 xmlAttrPtr attr = NULL;
680 int exists = 0;
681 int test = 0;
682 zval tmp_zv;
683
684 if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) {
686 if (UNEXPECTED(!str)) {
687 return 0;
688 }
689 ZVAL_STR(&tmp_zv, str);
690 member = &tmp_zv;
691 }
692
693 sxe = php_sxe_fetch_object(object);
694
695 GET_NODE(sxe, node);
696
697 if (Z_TYPE_P(member) == IS_LONG) {
698 if (sxe->iter.type != SXE_ITER_ATTRLIST) {
699 attribs = 0;
700 elements = 1;
701 if (sxe->iter.type == SXE_ITER_CHILD) {
702 node = php_sxe_get_first_node_non_destructive(sxe, node);
703 }
704 }
705 }
706
707 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
708 attribs = 1;
709 elements = 0;
710 node = php_sxe_get_first_node_non_destructive(sxe, node);
711 attr = (xmlAttrPtr)node;
712 test = sxe->iter.name != NULL;
713 } else if (sxe->iter.type != SXE_ITER_CHILD) {
714 node = php_sxe_get_first_node_non_destructive(sxe, node);
715 attr = node ? node->properties : NULL;
716 test = 0;
717 }
718
719 if (node) {
720 if (attribs) {
721 if (Z_TYPE_P(member) == IS_LONG) {
722 int nodendx = 0;
723
724 while (attr && nodendx <= Z_LVAL_P(member)) {
725 if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && match_ns((xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
726 if (nodendx == Z_LVAL_P(member)) {
727 exists = 1;
728 break;
729 }
730 nodendx++;
731 }
732 attr = attr->next;
733 }
734 } else {
735 while (attr) {
736 if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && xmlStrEqual(attr->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns((xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
737 exists = 1;
738 break;
739 }
740
741 attr = attr->next;
742 }
743 }
744 if (exists && check_empty == 1 &&
745 (!attr->children || !attr->children->content || !attr->children->content[0] || xmlStrEqual(attr->children->content, (const xmlChar *) "0")) ) {
746 /* Attribute with no content in its text node */
747 exists = 0;
748 }
749 }
750
751 if (elements) {
752 if (Z_TYPE_P(member) == IS_LONG) {
753 if (sxe->iter.type == SXE_ITER_CHILD) {
754 node = php_sxe_get_first_node_non_destructive(sxe, node);
755 }
756 node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
757 } else {
758 node = sxe_find_element_by_name(sxe, node->children, Z_STR_P(member));
759 }
760 if (node) {
761 exists = 1;
762 if (check_empty == 1 &&
763 (!node->children || (node->children->type == XML_TEXT_NODE && !node->children->next &&
764 (!node->children->content || !node->children->content[0] || xmlStrEqual(node->children->content, (const xmlChar *) "0")))) ) {
765 exists = 0;
766 }
767 }
768 }
769 }
770
771 if (member == &tmp_zv) {
772 zval_ptr_dtor_str(&tmp_zv);
773 }
774
775 return exists;
776}
777/* }}} */
778
779/* {{{ sxe_property_exists() */
780static int sxe_property_exists(zend_object *object, zend_string *name, int check_empty, void **cache_slot)
781{
782 zval member;
783 ZVAL_STR(&member, name);
784 return sxe_prop_dim_exists(object, &member, check_empty, 1, 0);
785}
786/* }}} */
787
788/* {{{ sxe_dimension_exists() */
789static int sxe_dimension_exists(zend_object *object, zval *member, int check_empty)
790{
791 return sxe_prop_dim_exists(object, member, check_empty, 0, 1);
792}
793/* }}} */
794
795/* {{{ sxe_prop_dim_delete() */
796static void sxe_prop_dim_delete(zend_object *object, zval *member, bool elements, bool attribs)
797{
798 php_sxe_object *sxe;
799 xmlNodePtr node;
800 xmlNodePtr nnext;
801 xmlAttrPtr attr = NULL;
802 xmlAttrPtr anext;
803 zval tmp_zv;
804 int test = 0;
805
806 if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) {
808 if (UNEXPECTED(!str)) {
809 return;
810 }
811 ZVAL_STR(&tmp_zv, str);
812 member = &tmp_zv;
813 }
814
815 sxe = php_sxe_fetch_object(object);
816
817 GET_NODE(sxe, node);
818
819 if (Z_TYPE_P(member) == IS_LONG) {
820 if (sxe->iter.type != SXE_ITER_ATTRLIST) {
821 attribs = 0;
822 elements = 1;
823 if (sxe->iter.type == SXE_ITER_CHILD) {
824 node = php_sxe_get_first_node_non_destructive(sxe, node);
825 }
826 }
827 }
828
829 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
830 attribs = 1;
831 elements = 0;
832 node = php_sxe_get_first_node_non_destructive(sxe, node);
833 attr = (xmlAttrPtr)node;
834 test = sxe->iter.name != NULL;
835 } else if (sxe->iter.type != SXE_ITER_CHILD) {
836 node = php_sxe_get_first_node_non_destructive(sxe, node);
837 attr = node ? node->properties : NULL;
838 test = 0;
839 }
840
841 if (node) {
842 php_libxml_invalidate_node_list_cache_from_doc(node->doc);
843
844 if (attribs) {
845 if (Z_TYPE_P(member) == IS_LONG) {
846 int nodendx = 0;
847
848 while (attr && nodendx <= Z_LVAL_P(member)) {
849 if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && match_ns((xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
850 if (nodendx == Z_LVAL_P(member)) {
851 sxe_unlink_node((xmlNodePtr) attr);
852 break;
853 }
854 nodendx++;
855 }
856 attr = attr->next;
857 }
858 } else {
859 while (attr) {
860 anext = attr->next;
861 if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && xmlStrEqual(attr->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns((xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
862 sxe_unlink_node((xmlNodePtr) attr);
863 break;
864 }
865 attr = anext;
866 }
867 }
868 }
869
870 if (elements) {
871 if (Z_TYPE_P(member) == IS_LONG) {
872 if (sxe->iter.type == SXE_ITER_CHILD) {
873 node = php_sxe_get_first_node_non_destructive(sxe, node);
874 }
875 node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
876 if (node) {
877 sxe_unlink_node(node);
878 }
879 } else {
880 node = node->children;
881 while (node) {
882 nnext = node->next;
883
884 SKIP_TEXT(node);
885
886 if (xmlStrEqual(node->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
887 sxe_unlink_node(node);
888 }
889
890next_iter:
891 node = nnext;
892 }
893 }
894 }
895 }
896
897 if (member == &tmp_zv) {
898 zval_ptr_dtor_str(&tmp_zv);
899 }
900}
901/* }}} */
902
903/* {{{ sxe_property_delete() */
904static void sxe_property_delete(zend_object *object, zend_string *name, void **cache_slot)
905{
906 zval member;
907 ZVAL_STR(&member, name);
908 sxe_prop_dim_delete(object, &member, 1, 0);
909}
910/* }}} */
911
912/* {{{ sxe_dimension_unset() */
913static void sxe_dimension_delete(zend_object *object, zval *offset)
914{
915 sxe_prop_dim_delete(object, offset, 0, 1);
916}
917/* }}} */
918
919static inline zend_string *sxe_xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) /* {{{ */
920{
921 xmlChar *tmp = xmlNodeListGetString(doc, list, inLine);
923
924 if (tmp) {
925 res = zend_string_init((char*)tmp, strlen((char *)tmp), 0);
926 xmlFree(tmp);
927 } else {
929 }
930
931 return res;
932}
933/* }}} */
934
935/* {{{ get_base_node_value() */
936static void get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval *value, zend_string *nsprefix, int isprefix)
937{
938 php_sxe_object *subnode;
939 xmlChar *contents;
940
941 if (node->children && node->children->type == XML_TEXT_NODE && !xmlIsBlankNode(node->children)) {
942 contents = xmlNodeListGetString(node->doc, node->children, 1);
943 if (contents) {
944 ZVAL_STRING(value, (char *)contents);
945 xmlFree(contents);
946 }
947 } else {
948 subnode = php_sxe_object_new(sxe_ref->zo.ce, sxe_ref->fptr_count);
949 subnode->document = sxe_ref->document;
950 subnode->document->refcount++;
951 if (nsprefix && *ZSTR_VAL(nsprefix)) {
952 subnode->iter.nsprefix = zend_string_copy(nsprefix);
953 subnode->iter.isprefix = isprefix;
954 }
955 php_libxml_increment_node_ptr((php_libxml_node_object *)subnode, node, NULL);
956
957 ZVAL_OBJ(value, &subnode->zo);
958 /*zval_add_ref(value);*/
959 }
960}
961/* }}} */
962
963static void sxe_properties_add(HashTable *rv, char *name, int namelen, zval *value) /* {{{ */
964{
966 zval *data_ptr;
967 zval newptr;
968
969 key = zend_string_init(name, namelen, 0);
970 if ((data_ptr = zend_hash_find(rv, key)) != NULL) {
971 if (Z_TYPE_P(data_ptr) == IS_ARRAY) {
973 } else {
974 array_init(&newptr);
975 zend_hash_next_index_insert_new(Z_ARRVAL(newptr), data_ptr);
977 ZVAL_ARR(data_ptr, Z_ARR(newptr));
978 }
979 } else {
981 }
983}
984/* }}} */
985
986static int sxe_prop_is_empty(zend_object *object) /* {{{ */
987{
988 php_sxe_object *sxe;
989 xmlNodePtr node;
990 xmlAttrPtr attr;
991 int test;
992 int is_empty;
993 bool use_iter = false;
994
995 sxe = php_sxe_fetch_object(object);
996
997 GET_NODE(sxe, node);
998 if (!node) {
999 return 1;
1000 }
1001
1002 if (sxe->iter.type == SXE_ITER_ELEMENT) {
1003 node = php_sxe_get_first_node_non_destructive(sxe, node);
1004 }
1005 if (node && node->type != XML_ENTITY_DECL) {
1006 attr = node->properties;
1007 test = sxe->iter.name && sxe->iter.type == SXE_ITER_ATTRLIST;
1008 while (attr) {
1009 if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && match_ns((xmlNodePtr)attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
1010 return 0;
1011 }
1012 attr = attr->next;
1013 }
1014 }
1015
1016 GET_NODE(sxe, node);
1017 node = php_sxe_get_first_node_non_destructive(sxe, node);
1018 is_empty = 1;
1019 if (node && sxe->iter.type != SXE_ITER_ATTRLIST) {
1020 if (node->type == XML_ATTRIBUTE_NODE) {
1021 return 0;
1022 } else if (sxe->iter.type != SXE_ITER_CHILD) {
1023 if (sxe->iter.type == SXE_ITER_NONE || !node->children || !node->parent || node->children->next || node->children->children || node->parent->children == node->parent->last) {
1024 node = node->children;
1025 } else {
1026 node = php_sxe_reset_iterator_no_clear_iter_data(sxe, 0);
1027 use_iter = true;
1028 }
1029 }
1030
1031 while (node) {
1032 if (node->children != NULL || node->prev != NULL || node->next != NULL) {
1033 SKIP_TEXT(node);
1034 } else {
1035 if (node->type == XML_TEXT_NODE) {
1036 const xmlChar *cur = node->content;
1037 if (*cur != 0) {
1038 is_empty = 0;
1039 break;
1040 }
1041 goto next_iter;
1042 }
1043 }
1044
1045 if (node->type == XML_ELEMENT_NODE && (! match_ns(node, sxe->iter.nsprefix, sxe->iter.isprefix))) {
1046 goto next_iter;
1047 }
1048
1049 if (!node->name) {
1050 goto next_iter;
1051 }
1052
1053 is_empty = 0;
1054 break;
1055next_iter:
1056 if (use_iter) {
1057 node = php_sxe_iterator_fetch(sxe, node->next, 0);
1058 } else {
1059 node = node->next;
1060 }
1061 }
1062 }
1063
1064 return is_empty;
1065}
1066/* }}} */
1067
1068static HashTable *sxe_get_prop_hash(zend_object *object, int is_debug) /* {{{ */
1069{
1070 zval value;
1071 zval zattr;
1072 HashTable *rv;
1073 php_sxe_object *sxe;
1074 char *name;
1075 xmlNodePtr node;
1076 xmlAttrPtr attr;
1077 int namelen;
1078 int test;
1079 bool use_iter = false;
1080
1081 sxe = php_sxe_fetch_object(object);
1082
1083 if (is_debug) {
1084 rv = zend_new_array(0);
1085 } else if (sxe->properties) {
1087 rv = sxe->properties;
1088 } else {
1089 rv = zend_new_array(0);
1090 sxe->properties = rv;
1091 }
1092
1093 GET_NODE(sxe, node);
1094 if (!node) {
1095 return rv;
1096 }
1097 if (is_debug || sxe->iter.type != SXE_ITER_CHILD) {
1098 if (sxe->iter.type == SXE_ITER_ELEMENT) {
1099 node = php_sxe_get_first_node_non_destructive(sxe, node);
1100 }
1101 if (node && node->type != XML_ENTITY_DECL) {
1102 attr = node->properties;
1103 ZVAL_UNDEF(&zattr);
1104 test = sxe->iter.name && sxe->iter.type == SXE_ITER_ATTRLIST;
1105 while (attr) {
1106 if ((!test || xmlStrEqual(attr->name, BAD_CAST ZSTR_VAL(sxe->iter.name))) && match_ns((xmlNodePtr)attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
1107 ZVAL_STR(&value, sxe_xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, attr->children, 1));
1108 namelen = xmlStrlen(attr->name);
1109 if (Z_ISUNDEF(zattr)) {
1110 array_init(&zattr);
1111 sxe_properties_add(rv, "@attributes", sizeof("@attributes") - 1, &zattr);
1112 }
1113 add_assoc_zval_ex(&zattr, (char*)attr->name, namelen, &value);
1114 }
1115 attr = attr->next;
1116 }
1117 }
1118 }
1119
1120 GET_NODE(sxe, node);
1121 node = php_sxe_get_first_node_non_destructive(sxe, node);
1122
1123 if (node && sxe->iter.type != SXE_ITER_ATTRLIST) {
1124 if (node->type == XML_ATTRIBUTE_NODE) {
1125 ZVAL_STR(&value, sxe_xmlNodeListGetString(node->doc, node->children, 1));
1127 node = NULL;
1128 } else if (sxe->iter.type != SXE_ITER_CHILD) {
1129 if ( sxe->iter.type == SXE_ITER_NONE || !node->children || !node->parent || !node->next || node->children->next || node->children->children || node->parent->children == node->parent->last ) {
1130 node = node->children;
1131 } else {
1132 node = php_sxe_reset_iterator_no_clear_iter_data(sxe, 0);
1133 use_iter = true;
1134 }
1135 }
1136
1137 while (node) {
1138 if (node->children != NULL || node->prev != NULL || node->next != NULL || xmlIsBlankNode(node)) {
1139 SKIP_TEXT(node);
1140 } else {
1141 if (node->type == XML_TEXT_NODE) {
1142 const xmlChar *cur = node->content;
1143
1144 if (*cur != 0) {
1145 ZVAL_STR(&value, sxe_xmlNodeListGetString(node->doc, node, 1));
1147 }
1148 goto next_iter;
1149 }
1150 }
1151
1152 if (node->type == XML_ELEMENT_NODE && (! match_ns(node, sxe->iter.nsprefix, sxe->iter.isprefix))) {
1153 goto next_iter;
1154 }
1155
1156 name = (char *) node->name;
1157 if (!name) {
1158 goto next_iter;
1159 } else {
1160 namelen = xmlStrlen(node->name);
1161 }
1162
1163 get_base_node_value(sxe, node, &value, sxe->iter.nsprefix, sxe->iter.isprefix);
1164
1165 if ( use_iter ) {
1167 } else {
1168 sxe_properties_add(rv, name, namelen, &value);
1169 }
1170next_iter:
1171 if (UNEXPECTED(node->type == XML_ENTITY_DECL)) {
1172 /* Entity decls are linked together via the next pointer.
1173 * The only way to get to an entity decl is via an entity reference in the document.
1174 * If we then continue iterating, we'll end up in the DTD. Even worse, if the entities reference each other we'll infinite loop. */
1175 break;
1176 }
1177 if (use_iter) {
1178 node = php_sxe_iterator_fetch(sxe, node->next, 0);
1179 } else {
1180 node = node->next;
1181 }
1182 }
1183 }
1184
1185 return rv;
1186}
1187/* }}} */
1188
1189static HashTable *sxe_get_gc(zend_object *object, zval **table, int *n) /* {{{ */ {
1190 php_sxe_object *sxe;
1191 sxe = php_sxe_fetch_object(object);
1192
1193 *table = NULL;
1194 *n = 0;
1195 return sxe->properties;
1196}
1197/* }}} */
1198
1199static HashTable *sxe_get_properties(zend_object *object) /* {{{ */
1200{
1201 return sxe_get_prop_hash(object, 0);
1202}
1203/* }}} */
1204
1205static HashTable * sxe_get_debug_info(zend_object *object, int *is_temp) /* {{{ */
1206{
1207 *is_temp = 1;
1208 return sxe_get_prop_hash(object, 1);
1209}
1210/* }}} */
1211
1212static int sxe_objects_compare(zval *object1, zval *object2) /* {{{ */
1213{
1214 php_sxe_object *sxe1;
1215 php_sxe_object *sxe2;
1216
1217 ZEND_COMPARE_OBJECTS_FALLBACK(object1, object2);
1218
1219 sxe1 = Z_SXEOBJ_P(object1);
1220 sxe2 = Z_SXEOBJ_P(object2);
1221
1222 if (sxe1->node != NULL && sxe2->node != NULL) {
1223 /* Both nodes set: Only support equality comparison between nodes. */
1224 if (sxe1->node == sxe2->node) {
1225 return 0;
1226 }
1227 return ZEND_UNCOMPARABLE;
1228 }
1229
1230 if (sxe1->node == NULL && sxe2->node == NULL) {
1231 /* Both nodes not set: Only support equality comparison between documents. */
1232 if (sxe1->document->ptr == sxe2->document->ptr) {
1233 return 0;
1234 }
1235 return ZEND_UNCOMPARABLE;
1236 }
1237
1238 /* Only one of the nodes set: Cannot compare. */
1239 return ZEND_UNCOMPARABLE;
1240}
1241/* }}} */
1242
1243/* {{{ Runs XPath query on the XML data */
1245{
1246 php_sxe_object *sxe;
1247 zval value;
1248 char *query;
1249 size_t query_len;
1250 int i;
1251 int nsnbr = 0;
1252 xmlNsPtr *ns = NULL;
1253 xmlXPathObjectPtr retval;
1254 xmlNodeSetPtr result;
1255 xmlNodePtr nodeptr;
1256
1257 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &query, &query_len) == FAILURE) {
1258 RETURN_THROWS();
1259 }
1260
1261 sxe = Z_SXEOBJ_P(ZEND_THIS);
1262
1263 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
1264 return; /* attributes don't have attributes */
1265 }
1266
1267 GET_NODE(sxe, nodeptr);
1268 nodeptr = php_sxe_get_first_node_non_destructive(sxe, nodeptr);
1269 if (!nodeptr) {
1270 return;
1271 }
1272
1273 if (!sxe->xpath) {
1274 sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
1275 }
1276 sxe->xpath->node = nodeptr;
1277
1278 ns = xmlGetNsList((xmlDocPtr) sxe->document->ptr, nodeptr);
1279 if (ns != NULL) {
1280 while (ns[nsnbr] != NULL) {
1281 nsnbr++;
1282 }
1283 }
1284
1285 sxe->xpath->namespaces = ns;
1286 sxe->xpath->nsNr = nsnbr;
1287
1288 retval = xmlXPathEval((xmlChar *)query, sxe->xpath);
1289 if (ns != NULL) {
1290 xmlFree(ns);
1291 sxe->xpath->namespaces = NULL;
1292 sxe->xpath->nsNr = 0;
1293 }
1294
1295 if (!retval) {
1297 }
1298
1299 result = retval->nodesetval;
1300
1301 if (result != NULL) {
1304
1305 for (i = 0; i < result->nodeNr; ++i) {
1306 nodeptr = result->nodeTab[i];
1307 if (nodeptr->type == XML_TEXT_NODE || nodeptr->type == XML_ELEMENT_NODE || nodeptr->type == XML_ATTRIBUTE_NODE || nodeptr->type == XML_PI_NODE || nodeptr->type == XML_COMMENT_NODE) {
1313 if (nodeptr->type == XML_TEXT_NODE) {
1314 node_as_zval(sxe, nodeptr->parent, &value, SXE_ITER_NONE, NULL, NULL, 0);
1315 } else if (nodeptr->type == XML_ATTRIBUTE_NODE) {
1316 node_as_zval_str(sxe, nodeptr->parent, &value, SXE_ITER_ATTRLIST, nodeptr->name, nodeptr->ns ? BAD_CAST nodeptr->ns->href : NULL, 0);
1317 } else {
1318 node_as_zval(sxe, nodeptr, &value, SXE_ITER_NONE, NULL, NULL, 0);
1319 }
1320
1321 add_next_index_zval(return_value, &value);
1322 }
1323 }
1324 } else {
1326 }
1327
1328 xmlXPathFreeObject(retval);
1329}
1330/* }}} */
1331
1332/* {{{ Creates a prefix/ns context for the next XPath query */
1333PHP_METHOD(SimpleXMLElement, registerXPathNamespace)
1334{
1335 php_sxe_object *sxe;
1336 size_t prefix_len, ns_uri_len;
1337 char *prefix, *ns_uri;
1338
1339 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &prefix, &prefix_len, &ns_uri, &ns_uri_len) == FAILURE) {
1340 RETURN_THROWS();
1341 }
1342
1343 sxe = Z_SXEOBJ_P(ZEND_THIS);
1344 if (!sxe->document) {
1345 zend_throw_error(NULL, "SimpleXMLElement is not properly initialized");
1346 RETURN_THROWS();
1347 }
1348
1349 if (!sxe->xpath) {
1350 sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
1351 }
1352
1353 if (xmlXPathRegisterNs(sxe->xpath, (xmlChar *)prefix, (xmlChar *)ns_uri) != 0) {
1355 }
1357}
1358
1359/* }}} */
1360
1361/* {{{ Return a well-formed XML string based on SimpleXML element */
1363{
1364 php_sxe_object *sxe;
1365 xmlNodePtr node;
1366 char *filename = NULL;
1367 size_t filename_len;
1368
1369 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|p!", &filename, &filename_len) == FAILURE) {
1370 RETURN_THROWS();
1371 }
1372
1373 sxe = Z_SXEOBJ_P(ZEND_THIS);
1374 GET_NODE(sxe, node);
1375 node = php_sxe_get_first_node_non_destructive(sxe, node);
1376
1377 if (!node) {
1379 }
1380
1381 xmlDocPtr doc = sxe->document->ptr;
1382
1383 if (filename) {
1384 zend_long bytes;
1385 if (node->parent && (XML_DOCUMENT_NODE == node->parent->type)) {
1386 bytes = sxe->document->handlers->dump_doc_to_file(filename, doc, false, (const char *) doc->encoding);
1387 } else {
1388 bytes = sxe->document->handlers->dump_node_to_file(filename, doc, node, false, NULL);
1389 }
1390 if (bytes == -1) {
1392 } else {
1394 }
1395 }
1396
1398 if (node->parent && (XML_DOCUMENT_NODE == node->parent->type)) {
1399 result = sxe->document->handlers->dump_doc_to_str(doc, 0, (const char *) doc->encoding);
1400 } else {
1401 result = sxe->document->handlers->dump_node_to_str(doc, node, false, (const char *) doc->encoding);
1402 }
1403
1404 if (!result) {
1406 } else {
1408 }
1409}
1410/* }}} */
1411
1412#define SXE_NS_PREFIX(ns) (ns->prefix ? (char*)ns->prefix : "")
1413
1414static inline void sxe_add_namespace_name_raw(zval *return_value, const char *prefix, const char *href)
1415{
1416 zend_string *key = zend_string_init(prefix, strlen(prefix), 0);
1417 zval zv;
1418
1419 if (!zend_hash_exists(Z_ARRVAL_P(return_value), key)) {
1420 ZVAL_STRING(&zv, href);
1422 }
1424}
1425
1426static inline void sxe_add_namespace_name(zval *return_value, xmlNsPtr ns) /* {{{ */
1427{
1428 char *prefix = SXE_NS_PREFIX(ns);
1429 sxe_add_namespace_name_raw(return_value, prefix, (const char *) ns->href);
1430}
1431/* }}} */
1432
1433static void sxe_add_namespaces(php_sxe_object *sxe, xmlNodePtr node, bool recursive, zval *return_value) /* {{{ */
1434{
1435 xmlAttrPtr attr;
1436
1437 if (node->ns) {
1438 sxe_add_namespace_name(return_value, node->ns);
1439 }
1440
1441 attr = node->properties;
1442 while (attr) {
1443 if (attr->ns) {
1444 sxe_add_namespace_name(return_value, attr->ns);
1445 }
1446 attr = attr->next;
1447 }
1448
1449 if (recursive) {
1450 node = node->children;
1451 while (node) {
1452 if (node->type == XML_ELEMENT_NODE) {
1453 sxe_add_namespaces(sxe, node, recursive, return_value);
1454 }
1455 node = node->next;
1456 }
1457 }
1458} /* }}} */
1459
1460static inline void sxe_object_free_iterxpath(php_sxe_object *sxe)
1461{
1462 if (!Z_ISUNDEF(sxe->iter.data)) {
1463 zval_ptr_dtor(&sxe->iter.data);
1464 ZVAL_UNDEF(&sxe->iter.data);
1465 }
1466
1467 if (sxe->iter.name) {
1468 zend_string_release(sxe->iter.name);
1469 sxe->iter.name = NULL;
1470 }
1471 if (sxe->iter.nsprefix) {
1472 zend_string_release(sxe->iter.nsprefix);
1473 sxe->iter.nsprefix = NULL;
1474 }
1475 if (!Z_ISUNDEF(sxe->tmp)) {
1476 zval_ptr_dtor(&sxe->tmp);
1477 ZVAL_UNDEF(&sxe->tmp);
1478 }
1479
1480 php_libxml_node_decrement_resource((php_libxml_node_object *)sxe);
1481
1482 if (sxe->xpath) {
1483 xmlXPathFreeContext(sxe->xpath);
1484 sxe->xpath = NULL;
1485 }
1486}
1487
1488
1489/* {{{ Return all namespaces in use */
1490PHP_METHOD(SimpleXMLElement, getNamespaces)
1491{
1492 bool recursive = 0;
1493 php_sxe_object *sxe;
1494 xmlNodePtr node;
1495
1496 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &recursive) == FAILURE) {
1497 RETURN_THROWS();
1498 }
1499
1501
1502 sxe = Z_SXEOBJ_P(ZEND_THIS);
1503 GET_NODE(sxe, node);
1504 node = php_sxe_get_first_node_non_destructive(sxe, node);
1505
1506 if (node) {
1507 if (node->type == XML_ELEMENT_NODE) {
1508 sxe_add_namespaces(sxe, node, recursive, return_value);
1509 } else if (node->type == XML_ATTRIBUTE_NODE && node->ns) {
1510 sxe_add_namespace_name(return_value, node->ns);
1511 }
1512 }
1513}
1514/* }}} */
1515
1516static void sxe_add_registered_namespaces(php_sxe_object *sxe, xmlNodePtr node, bool recursive, bool include_xmlns_attributes, zval *return_value) /* {{{ */
1517{
1518 xmlNsPtr ns;
1519
1520 if (node->type == XML_ELEMENT_NODE) {
1521 ns = node->nsDef;
1522 while (ns != NULL) {
1523 sxe_add_namespace_name(return_value, ns);
1524 ns = ns->next;
1525 }
1526 if (include_xmlns_attributes) {
1527 for (const xmlAttr *attr = node->properties; attr; attr = attr->next) {
1528 /* Attributes in the xmlns namespace should be treated as namespace declarations too. */
1529 if (attr->ns && xmlStrEqual(attr->ns->href, (const xmlChar *) "http://www.w3.org/2000/xmlns/")) {
1530 const char *prefix = attr->ns->prefix ? (const char *) attr->name : "";
1531 bool free;
1532 xmlChar *href = php_libxml_attr_value(attr, &free);
1533 sxe_add_namespace_name_raw(return_value, prefix, (const char *) href);
1534 if (free) {
1535 xmlFree(href);
1536 }
1537 }
1538 }
1539 }
1540 if (recursive) {
1541 node = node->children;
1542 while (node) {
1543 sxe_add_registered_namespaces(sxe, node, recursive, include_xmlns_attributes, return_value);
1544 node = node->next;
1545 }
1546 }
1547 }
1548}
1549/* }}} */
1550
1551/* {{{ Return all namespaces registered with document */
1552PHP_METHOD(SimpleXMLElement, getDocNamespaces)
1553{
1554 bool recursive = 0, from_root = 1;
1555 php_sxe_object *sxe;
1556 xmlNodePtr node;
1557
1558 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|bb", &recursive, &from_root) == FAILURE) {
1559 RETURN_THROWS();
1560 }
1561
1562 sxe = Z_SXEOBJ_P(ZEND_THIS);
1563 if (from_root) {
1564 if (!sxe->document) {
1565 zend_throw_error(NULL, "SimpleXMLElement is not properly initialized");
1566 RETURN_THROWS();
1567 }
1568
1569 node = xmlDocGetRootElement((xmlDocPtr)sxe->document->ptr);
1570 } else {
1571 GET_NODE(sxe, node);
1572 }
1573
1574 if (node == NULL) {
1576 }
1577
1578 /* Only do this for modern documents to keep BC. */
1579 bool include_xmlns_attributes = sxe->document->class_type == PHP_LIBXML_CLASS_MODERN;
1580
1582 sxe_add_registered_namespaces(sxe, node, recursive, include_xmlns_attributes, return_value);
1583}
1584/* }}} */
1585
1586/* {{{ Finds children of given node */
1588{
1589 php_sxe_object *sxe;
1590 zend_string *nsprefix = NULL;
1591 xmlNodePtr node;
1592 bool isprefix = 0;
1593
1594 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!b", &nsprefix, &isprefix) == FAILURE) {
1595 RETURN_THROWS();
1596 }
1597
1598 sxe = Z_SXEOBJ_P(ZEND_THIS);
1599
1600 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
1601 return; /* attributes don't have attributes */
1602 }
1603
1604 GET_NODE(sxe, node);
1605 node = php_sxe_get_first_node_non_destructive(sxe, node);
1606 if (!node) {
1607 return;
1608 }
1609
1610 node_as_zval(sxe, node, return_value, SXE_ITER_CHILD, NULL, nsprefix, isprefix);
1611}
1612/* }}} */
1613
1614/* {{{ Returns name of given node */
1616{
1617 php_sxe_object *sxe;
1618 xmlNodePtr node;
1619 int namelen;
1620
1622 RETURN_THROWS();
1623 }
1624
1625 sxe = Z_SXEOBJ_P(ZEND_THIS);
1626
1627 GET_NODE(sxe, node);
1628 node = php_sxe_get_first_node_non_destructive(sxe, node);
1629 if (node) {
1630 namelen = xmlStrlen(node->name);
1631 RETURN_STRINGL((char*)node->name, namelen);
1632 } else {
1634 }
1635}
1636/* }}} */
1637
1638/* {{{ Identifies an element's attributes */
1639PHP_METHOD(SimpleXMLElement, attributes)
1640{
1641 php_sxe_object *sxe;
1642 zend_string *nsprefix = NULL;
1643 xmlNodePtr node;
1644 bool isprefix = 0;
1645
1646 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!b", &nsprefix, &isprefix) == FAILURE) {
1647 RETURN_THROWS();
1648 }
1649
1650 sxe = Z_SXEOBJ_P(ZEND_THIS);
1651 GET_NODE(sxe, node);
1652 node = php_sxe_get_first_node_non_destructive(sxe, node);
1653 if (!node) {
1654 return;
1655 }
1656
1657 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
1658 return; /* attributes don't have attributes */
1659 }
1660
1661 node_as_zval(sxe, node, return_value, SXE_ITER_ATTRLIST, NULL, nsprefix, isprefix);
1662}
1663/* }}} */
1664
1665/* {{{ Add Element with optional namespace information */
1667{
1668 php_sxe_object *sxe;
1669 char *qname, *value = NULL, *nsuri = NULL;
1670 size_t qname_len, value_len = 0, nsuri_len = 0;
1671 xmlNodePtr node, newnode;
1672 xmlNsPtr nsptr = NULL;
1673 xmlChar *localname, *prefix = NULL;
1674
1675 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!s!",
1676 &qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
1677 RETURN_THROWS();
1678 }
1679
1680 if (qname_len == 0) {
1682 RETURN_THROWS();
1683 }
1684
1685 sxe = Z_SXEOBJ_P(ZEND_THIS);
1686 GET_NODE(sxe, node);
1687
1688 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
1689 php_error_docref(NULL, E_WARNING, "Cannot add element to attributes");
1690 return;
1691 }
1692
1693 node = php_sxe_get_first_node_non_destructive(sxe, node);
1694
1695 if (node == NULL) {
1696 php_error_docref(NULL, E_WARNING, "Cannot add child. Parent is not a permanent member of the XML tree");
1697 return;
1698 }
1699
1700 php_libxml_invalidate_node_list_cache_from_doc(node->doc);
1701
1702 localname = xmlSplitQName2((xmlChar *)qname, &prefix);
1703 if (localname == NULL) {
1704 localname = xmlStrdup((xmlChar *)qname);
1705 }
1706
1707 newnode = xmlNewChild(node, NULL, localname, (xmlChar *)value);
1708
1709 if (nsuri != NULL) {
1710 if (nsuri_len == 0) {
1711 newnode->ns = NULL;
1712 nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix);
1713 } else {
1714 nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri);
1715 if (nsptr == NULL) {
1716 nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix);
1717 }
1718 newnode->ns = nsptr;
1719 }
1720 }
1721
1722 node_as_zval_str(sxe, newnode, return_value, SXE_ITER_NONE, localname, prefix, 0);
1723
1724 xmlFree(localname);
1725 if (prefix != NULL) {
1726 xmlFree(prefix);
1727 }
1728}
1729/* }}} */
1730
1731/* {{{ Add Attribute with optional namespace information */
1732PHP_METHOD(SimpleXMLElement, addAttribute)
1733{
1734 php_sxe_object *sxe;
1735 char *qname, *value = NULL, *nsuri = NULL;
1736 size_t qname_len, value_len = 0, nsuri_len = 0;
1737 xmlNodePtr node;
1738 xmlAttrPtr attrp = NULL;
1739 xmlNsPtr nsptr = NULL;
1740 xmlChar *localname, *prefix = NULL;
1741
1742 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|s!",
1743 &qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
1744 RETURN_THROWS();
1745 }
1746
1747 if (qname_len == 0) {
1749 RETURN_THROWS();
1750 }
1751
1752 sxe = Z_SXEOBJ_P(ZEND_THIS);
1753 GET_NODE(sxe, node);
1754
1755 node = php_sxe_get_first_node_non_destructive(sxe, node);
1756
1757 if (node && node->type != XML_ELEMENT_NODE) {
1758 node = node->parent;
1759 }
1760
1761 if (node == NULL) {
1762 php_error_docref(NULL, E_WARNING, "Unable to locate parent Element");
1763 return;
1764 }
1765
1766 localname = xmlSplitQName2((xmlChar *)qname, &prefix);
1767 bool free_localname = localname != NULL;
1768 if (!free_localname) {
1769 if (nsuri_len > 0) {
1770 if (prefix != NULL) {
1771 xmlFree(prefix);
1772 }
1773 php_error_docref(NULL, E_WARNING, "Attribute requires prefix for namespace");
1774 return;
1775 }
1776 localname = (xmlChar *) qname;
1777 }
1778
1779 attrp = xmlHasNsProp(node, localname, (xmlChar *)nsuri);
1780 if (attrp != NULL && attrp->type != XML_ATTRIBUTE_DECL) {
1781 php_error_docref(NULL, E_WARNING, "Attribute already exists");
1782 goto out;
1783 }
1784
1785 if (nsuri != NULL) {
1786 nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri);
1787 if (nsptr == NULL) {
1788 nsptr = xmlNewNs(node, (xmlChar *)nsuri, prefix);
1789 }
1790 }
1791
1792 attrp = xmlNewNsProp(node, nsptr, localname, (xmlChar *)value);
1793
1794out:
1795 if (free_localname) {
1796 xmlFree(localname);
1797 }
1798 if (prefix != NULL) {
1799 xmlFree(prefix);
1800 }
1801}
1802/* }}} */
1803
1804/* {{{ cast_object() */
1805static zend_result cast_object(zval *object, int type, char *contents)
1806{
1807 if (contents) {
1809 } else {
1810 ZVAL_NULL(object);
1811 }
1812
1813 switch (type) {
1814 case IS_STRING:
1815 convert_to_string(object);
1816 break;
1817 case IS_LONG:
1818 convert_to_long(object);
1819 break;
1820 case IS_DOUBLE:
1821 convert_to_double(object);
1822 break;
1823 case _IS_NUMBER:
1825 break;
1826 default:
1827 return FAILURE;
1828 }
1829 return SUCCESS;
1830}
1831/* }}} */
1832
1833/* {{{ sxe_object_cast() */
1834static zend_result sxe_object_cast_ex(zend_object *readobj, zval *writeobj, int type)
1835{
1836 php_sxe_object *sxe;
1837 xmlChar *contents = NULL;
1838 bool free_contents = true;
1839 xmlNodePtr node;
1841
1842 sxe = php_sxe_fetch_object(readobj);
1843
1844 if (type == _IS_BOOL) {
1845 node = php_sxe_get_first_node_non_destructive(sxe, NULL);
1846 if (node) {
1847 ZVAL_TRUE(writeobj);
1848 } else {
1849 ZVAL_BOOL(writeobj, !sxe_prop_is_empty(readobj));
1850 }
1851 return SUCCESS;
1852 }
1853
1854 if (sxe->iter.type != SXE_ITER_NONE) {
1855 node = php_sxe_get_first_node_non_destructive(sxe, NULL);
1856 if (node) {
1857 contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, node->children, 1);
1858 }
1859 } else {
1860 if (!sxe->node) {
1861 if (sxe->document) {
1862 php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement((xmlDocPtr) sxe->document->ptr), NULL);
1863 }
1864 }
1865
1866 if (sxe->node && sxe->node->node) {
1867 if (sxe->node->node->children) {
1868 contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, sxe->node->node->children, 1);
1869 } else if (sxe->node->node->type == XML_COMMENT_NODE || sxe->node->node->type == XML_PI_NODE) {
1870 contents = sxe->node->node->content;
1871 free_contents = false;
1872 }
1873 }
1874 }
1875
1876 rv = cast_object(writeobj, type, (char *)contents);
1877
1878 if (contents && free_contents) {
1879 xmlFree(contents);
1880 }
1881
1882 return rv;
1883}
1884/* }}} */
1885
1886/* {{{ Variant of sxe_object_cast_ex that handles overwritten __toString() method */
1887static zend_result sxe_object_cast(zend_object *readobj, zval *writeobj, int type)
1888{
1889 if (type == IS_STRING
1890 && zend_std_cast_object_tostring(readobj, writeobj, IS_STRING) == SUCCESS
1891 ) {
1892 return SUCCESS;
1893 }
1894
1895 return sxe_object_cast_ex(readobj, writeobj, type);
1896}
1897/* }}} */
1898
1899/* {{{ Returns the string content */
1900PHP_METHOD(SimpleXMLElement, __toString)
1901{
1903 RETURN_THROWS();
1904 }
1905
1906 zend_result rv = sxe_object_cast_ex(Z_OBJ_P(ZEND_THIS), return_value, IS_STRING);
1909}
1910/* }}} */
1911
1912static zend_long php_sxe_count_elements_helper(php_sxe_object *sxe) /* {{{ */
1913{
1914 zend_long count = 0;
1915 xmlNodePtr node = php_sxe_reset_iterator_no_clear_iter_data(sxe, 0);
1916
1917 while (node)
1918 {
1919 count++;
1920 node = php_sxe_iterator_fetch(sxe, node->next, 0);
1921 }
1922
1923 return count;
1924}
1925/* }}} */
1926
1927static zend_result sxe_count_elements(zend_object *object, zend_long *count) /* {{{ */
1928{
1929 php_sxe_object *intern;
1930 intern = php_sxe_fetch_object(object);
1931 if (intern->fptr_count) {
1932 zval rv;
1933 zend_call_method_with_0_params(object, intern->zo.ce, &intern->fptr_count, "count", &rv);
1934 if (!Z_ISUNDEF(rv)) {
1935 /* TODO: change this to Z_LVAL_P() once the tentative type on count() is gone. */
1936 *count = zval_get_long(&rv);
1937 zval_ptr_dtor(&rv);
1938 return SUCCESS;
1939 }
1940 return FAILURE;
1941 }
1942 *count = php_sxe_count_elements_helper(intern);
1943 return SUCCESS;
1944}
1945/* }}} */
1946
1947/* {{{ Get number of child elements */
1949{
1951
1953 RETURN_THROWS();
1954 }
1955
1956 RETURN_LONG(php_sxe_count_elements_helper(sxe));
1957}
1958/* }}} */
1959
1960
1961/* {{{ Rewind to first element */
1963{
1965 RETURN_THROWS();
1966 }
1967
1969}
1970/* }}} */
1971
1972/* {{{ Check whether iteration is valid */
1974{
1976
1978 RETURN_THROWS();
1979 }
1980
1982}
1983/* }}} */
1984
1985/* {{{ Get current element */
1987{
1989
1991 RETURN_THROWS();
1992 }
1993
1994 if (Z_ISUNDEF(sxe->iter.data)) {
1995 zend_throw_error(NULL, "Iterator not initialized or already consumed");
1996 RETURN_THROWS();
1997 }
1998
2000}
2001/* }}} */
2002
2003/* {{{ Get name of current child element */
2005{
2006 xmlNodePtr curnode;
2007 php_sxe_object *intern;
2009
2011 RETURN_THROWS();
2012 }
2013
2014 if (Z_ISUNDEF(sxe->iter.data)) {
2015 zend_throw_error(NULL, "Iterator not initialized or already consumed");
2016 RETURN_THROWS();
2017 }
2018
2019 intern = Z_SXEOBJ_P(&sxe->iter.data);
2020 if (intern == NULL || intern->node == NULL) {
2021 zend_throw_error(NULL, "Iterator not initialized or already consumed");
2022 RETURN_THROWS();
2023 }
2024
2025 curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->node)->node;
2026 RETURN_STRINGL((char*)curnode->name, xmlStrlen(curnode->name));
2027}
2028/* }}} */
2029
2030/* {{{ Move to next element */
2032{
2034 RETURN_THROWS();
2035 }
2036
2038}
2039/* }}} */
2040
2041/* {{{ Check whether element has children (elements) */
2042PHP_METHOD(SimpleXMLElement, hasChildren)
2043{
2045 php_sxe_object *child;
2046 xmlNodePtr node;
2047
2049 RETURN_THROWS();
2050 }
2051
2052 if (Z_ISUNDEF(sxe->iter.data) || sxe->iter.type == SXE_ITER_ATTRLIST) {
2054 }
2055 child = Z_SXEOBJ_P(&sxe->iter.data);
2056
2057 GET_NODE(child, node);
2058 if (node) {
2059 node = node->children;
2060 }
2061 while (node && node->type != XML_ELEMENT_NODE) {
2062 node = node->next;
2063 }
2064 RETURN_BOOL(node ? 1 : 0);
2065}
2066/* }}} */
2067
2068/* {{{ Get child element iterator */
2069PHP_METHOD(SimpleXMLElement, getChildren)
2070{
2072
2074 RETURN_THROWS();
2075 }
2076
2077 if (Z_ISUNDEF(sxe->iter.data) || sxe->iter.type == SXE_ITER_ATTRLIST) {
2078 return; /* return NULL */
2079 }
2080
2082}
2083
2084static zend_object_handlers sxe_object_handlers;
2085
2086/* {{{ sxe_object_clone() */
2087static zend_object *
2088sxe_object_clone(zend_object *object)
2089{
2090 php_sxe_object *sxe = php_sxe_fetch_object(object);
2091 php_sxe_object *clone;
2092 xmlNodePtr nodep = NULL;
2093 xmlDocPtr docp = NULL;
2094 bool is_root_element = sxe->node && sxe->node->node && sxe->node->node->parent
2095 && (sxe->node->node->parent->type == XML_DOCUMENT_NODE || sxe->node->node->parent->type == XML_HTML_DOCUMENT_NODE);
2096
2097 clone = php_sxe_object_new(sxe->zo.ce, sxe->fptr_count);
2098
2099 if (is_root_element) {
2100 docp = xmlCopyDoc(sxe->document->ptr, 1);
2101 php_libxml_increment_doc_ref((php_libxml_node_object *)clone, docp);
2102 } else {
2103 clone->document = sxe->document;
2104 if (clone->document) {
2105 clone->document->refcount++;
2106 docp = clone->document->ptr;
2107 }
2108 }
2109
2110 clone->iter.isprefix = sxe->iter.isprefix;
2111 if (sxe->iter.name != NULL) {
2112 clone->iter.name = zend_string_copy(sxe->iter.name);
2113 }
2114 if (sxe->iter.nsprefix != NULL) {
2115 clone->iter.nsprefix = zend_string_copy(sxe->iter.nsprefix);
2116 }
2117 clone->iter.type = sxe->iter.type;
2118
2119 if (sxe->node) {
2120 if (is_root_element) {
2121 nodep = xmlDocGetRootElement(docp);
2122 } else {
2123 nodep = xmlDocCopyNode(sxe->node->node, docp, 1);
2124 }
2125 }
2126
2127 php_libxml_increment_node_ptr((php_libxml_node_object *)clone, nodep, NULL);
2128
2129 return &clone->zo;
2130}
2131/* }}} */
2132
2133/* {{{ sxe_object_free_storage() */
2134static void sxe_object_free_storage(zend_object *object)
2135{
2136 php_sxe_object *sxe;
2137
2138 sxe = php_sxe_fetch_object(object);
2139
2140 zend_object_std_dtor(&sxe->zo);
2141
2142 sxe_object_free_iterxpath(sxe);
2143
2144 if (sxe->properties) {
2146 zend_hash_release(sxe->properties);
2147 }
2148}
2149/* }}} */
2150
2151/* {{{ php_sxe_find_fptr_count() */
2152static zend_function* php_sxe_find_fptr_count(zend_class_entry *ce)
2153{
2154 zend_function *fptr_count = NULL;
2155 zend_class_entry *parent = ce;
2156 int inherited = 0;
2157
2158 while (parent) {
2159 if (parent == ce_SimpleXMLElement) {
2160 break;
2161 }
2162 parent = parent->parent;
2163 inherited = 1;
2164 }
2165
2166 if (inherited) {
2167 /* Find count() method */
2168 fptr_count = zend_hash_find_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_COUNT));
2169 if (fptr_count->common.scope == parent) {
2170 fptr_count = NULL;
2171 }
2172 }
2173
2174 return fptr_count;
2175}
2176/* }}} */
2177
2178/* {{{ php_sxe_object_new() */
2179static php_sxe_object* php_sxe_object_new(zend_class_entry *ce, zend_function *fptr_count)
2180{
2181 php_sxe_object *intern;
2182
2183 intern = zend_object_alloc(sizeof(php_sxe_object), ce);
2184
2185 intern->iter.type = SXE_ITER_NONE;
2186 intern->iter.nsprefix = NULL;
2187 intern->iter.name = NULL;
2188 intern->fptr_count = fptr_count;
2189
2190 zend_object_std_init(&intern->zo, ce);
2191 object_properties_init(&intern->zo, ce);
2192
2193 return intern;
2194}
2195/* }}} */
2196
2197/* {{{ sxe_object_new() */
2200{
2201 php_sxe_object *intern;
2202
2203 intern = php_sxe_object_new(ce, php_sxe_find_fptr_count(ce));
2204 return &intern->zo;
2205}
2206/* }}} */
2207
2208/* {{{ Load a filename and return a simplexml_element object to allow for processing */
2210{
2211 php_sxe_object *sxe;
2212 char *filename;
2213 size_t filename_len;
2214 xmlDocPtr docp;
2216 zend_long options = 0;
2218 zend_function *fptr_count;
2219 bool isprefix = 0;
2220
2221 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|C!lSb", &filename, &filename_len, &ce, &options, &ns, &isprefix) == FAILURE) {
2222 RETURN_THROWS();
2223 }
2224
2226 zend_argument_value_error(3, "is too large");
2227 RETURN_THROWS();
2228 }
2229
2230 PHP_LIBXML_SANITIZE_GLOBALS(read_file);
2231 docp = xmlReadFile(filename, NULL, (int)options);
2232 PHP_LIBXML_RESTORE_GLOBALS(read_file);
2233
2234 if (!docp) {
2236 }
2237
2238 if (!ce) {
2240 fptr_count = NULL;
2241 } else {
2242 fptr_count = php_sxe_find_fptr_count(ce);
2243 }
2244 sxe = php_sxe_object_new(ce, fptr_count);
2245 sxe->iter.nsprefix = ZSTR_LEN(ns) ? zend_string_copy(ns) : NULL;
2246 sxe->iter.isprefix = isprefix;
2247 php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp);
2248 php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL);
2249
2250 RETURN_OBJ(&sxe->zo);
2251}
2252/* }}} */
2253
2254/* {{{ Load a string and return a simplexml_element object to allow for processing */
2256{
2257 php_sxe_object *sxe;
2258 char *data;
2259 size_t data_len;
2260 xmlDocPtr docp;
2262 zend_long options = 0;
2264 zend_function *fptr_count;
2265 bool isprefix = 0;
2266
2267 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|C!lSb", &data, &data_len, &ce, &options, &ns, &isprefix) == FAILURE) {
2268 RETURN_THROWS();
2269 }
2270
2271 if (ZEND_SIZE_T_INT_OVFL(data_len)) {
2272 zend_argument_value_error(1, "is too long");
2273 RETURN_THROWS();
2274 }
2275 if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(ns))) {
2276 zend_argument_value_error(4, "is too long");
2277 RETURN_THROWS();
2278 }
2280 zend_argument_value_error(3, "is too large");
2281 RETURN_THROWS();
2282 }
2283
2284 PHP_LIBXML_SANITIZE_GLOBALS(read_memory);
2285 docp = xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options);
2286 PHP_LIBXML_RESTORE_GLOBALS(read_memory);
2287
2288 if (!docp) {
2290 }
2291
2292 if (!ce) {
2294 fptr_count = NULL;
2295 } else {
2296 fptr_count = php_sxe_find_fptr_count(ce);
2297 }
2298 sxe = php_sxe_object_new(ce, fptr_count);
2299 sxe->iter.nsprefix = ZSTR_LEN(ns) ? zend_string_copy(ns) : NULL;
2300 sxe->iter.isprefix = isprefix;
2301 php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp);
2302 php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL);
2303
2304 RETURN_OBJ(&sxe->zo);
2305}
2306/* }}} */
2307
2308/* {{{ SimpleXMLElement constructor */
2309PHP_METHOD(SimpleXMLElement, __construct)
2310{
2312 char *data;
2314 size_t data_len;
2315 xmlDocPtr docp;
2316 zend_long options = 0;
2317 bool is_url = 0, isprefix = 0;
2318
2319 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lbSb", &data, &data_len, &options, &is_url, &ns, &isprefix) == FAILURE) {
2320 RETURN_THROWS();
2321 }
2322
2323 if (ZEND_SIZE_T_INT_OVFL(data_len)) {
2324 zend_argument_error(zend_ce_exception, 1, "is too long");
2325 RETURN_THROWS();
2326 }
2327 if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(ns))) {
2328 zend_argument_error(zend_ce_exception, 4, "is too long");
2329 RETURN_THROWS();
2330 }
2332 zend_argument_error(zend_ce_exception, 2, "is invalid");
2333 RETURN_THROWS();
2334 }
2335
2336 PHP_LIBXML_SANITIZE_GLOBALS(read_file_or_memory);
2337 docp = is_url ? xmlReadFile(data, NULL, (int)options) : xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options);
2338 PHP_LIBXML_RESTORE_GLOBALS(read_file_or_memory);
2339
2340 if (!docp) {
2341 zend_throw_exception(zend_ce_exception, "String could not be parsed as XML", 0);
2342 RETURN_THROWS();
2343 }
2344
2345 sxe_object_free_iterxpath(sxe);
2346
2347 sxe->iter.nsprefix = ZSTR_LEN(ns) ? zend_string_copy(ns) : NULL;
2348 sxe->iter.isprefix = isprefix;
2349 php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp);
2350 php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL);
2351}
2352/* }}} */
2353
2354static const zend_object_iterator_funcs php_sxe_iterator_funcs = { /* {{{ */
2355 php_sxe_iterator_dtor,
2356 php_sxe_iterator_valid,
2357 php_sxe_iterator_current_data,
2358 php_sxe_iterator_current_key,
2359 php_sxe_iterator_move_forward,
2360 php_sxe_iterator_rewind,
2361 NULL,
2362 NULL, /* get_gc */
2363};
2364/* }}} */
2365
2366static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data) /* {{{ */
2367{
2369 int isprefix = sxe->iter.isprefix;
2370
2371 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
2372 if (sxe->iter.name) {
2373 while (node) {
2374 if (node->type == XML_ATTRIBUTE_NODE) {
2375 if (xmlStrEqual(node->name, BAD_CAST ZSTR_VAL(sxe->iter.name)) && match_ns(node, prefix, isprefix)) {
2376 break;
2377 }
2378 }
2379 node = node->next;
2380 }
2381 } else {
2382 while (node) {
2383 if (node->type == XML_ATTRIBUTE_NODE) {
2384 if (match_ns(node, prefix, isprefix)) {
2385 break;
2386 }
2387 }
2388 node = node->next;
2389 }
2390 }
2391 } else if (sxe->iter.type == SXE_ITER_ELEMENT && sxe->iter.name) {
2392 while (node) {
2393 if (node->type == XML_ELEMENT_NODE) {
2394 if (xmlStrEqual(node->name, BAD_CAST ZSTR_VAL(sxe->iter.name)) && match_ns(node, prefix, isprefix)) {
2395 break;
2396 }
2397 }
2398 node = node->next;
2399 }
2400 } else {
2401 while (node) {
2402 if (node->type == XML_ELEMENT_NODE) {
2403 if (match_ns(node, prefix, isprefix)) {
2404 break;
2405 }
2406 }
2407 node = node->next;
2408 }
2409 }
2410
2411 if (node && use_data) {
2412 node_as_zval(sxe, node, &sxe->iter.data, SXE_ITER_NONE, NULL, prefix, isprefix);
2413 }
2414
2415 return node;
2416}
2417/* }}} */
2418
2419static xmlNodePtr php_sxe_reset_iterator_no_clear_iter_data(php_sxe_object *sxe, int use_data)
2420{
2421 xmlNodePtr node;
2422 GET_NODE(sxe, node)
2423
2424 if (node) {
2425 switch (sxe->iter.type) {
2426 case SXE_ITER_ELEMENT:
2427 case SXE_ITER_CHILD:
2428 case SXE_ITER_NONE:
2429 node = node->children;
2430 break;
2431 case SXE_ITER_ATTRLIST:
2432 node = (xmlNodePtr) node->properties;
2433 }
2434 if (use_data) {
2436 }
2437 return php_sxe_iterator_fetch(sxe, node, use_data);
2438 }
2439 return NULL;
2440}
2441
2442static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe) /* {{{ */
2443{
2444 if (!Z_ISUNDEF(sxe->iter.data)) {
2445 zval_ptr_dtor(&sxe->iter.data);
2446 ZVAL_UNDEF(&sxe->iter.data);
2447 }
2448
2449 return php_sxe_reset_iterator_no_clear_iter_data(sxe, 1);
2450}
2451/* }}} */
2452
2453zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
2454{
2455 php_sxe_iterator *iterator;
2456
2457 if (by_ref) {
2458 zend_throw_error(NULL, "An iterator cannot be used with foreach by reference");
2459 return NULL;
2460 }
2461 iterator = emalloc(sizeof(php_sxe_iterator));
2462 zend_iterator_init(&iterator->intern);
2463
2464 ZVAL_OBJ_COPY(&iterator->intern.data, Z_OBJ_P(object));
2465 iterator->intern.funcs = &php_sxe_iterator_funcs;
2466 iterator->sxe = Z_SXEOBJ_P(object);
2467
2468 return (zend_object_iterator*)iterator;
2469}
2470/* }}} */
2471
2472static void php_sxe_iterator_dtor(zend_object_iterator *iter) /* {{{ */
2473{
2474 php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
2475
2476 /* cleanup handled in sxe_object_dtor as we don't always have an iterator wrapper */
2477 if (!Z_ISUNDEF(iterator->intern.data)) {
2478 zval_ptr_dtor(&iterator->intern.data);
2479 }
2480}
2481/* }}} */
2482
2483static zend_result php_sxe_iterator_valid(zend_object_iterator *iter) /* {{{ */
2484{
2485 php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
2486
2487 return Z_ISUNDEF(iterator->sxe->iter.data) ? FAILURE : SUCCESS;
2488}
2489/* }}} */
2490
2491static zval *php_sxe_iterator_current_data(zend_object_iterator *iter) /* {{{ */
2492{
2493 php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
2494
2495 zval *data = &iterator->sxe->iter.data;
2496 if (Z_ISUNDEF_P(data)) {
2497 return NULL;
2498 }
2499 return data;
2500}
2501/* }}} */
2502
2503static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key) /* {{{ */
2504{
2505 php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
2506 zval *curobj = &iterator->sxe->iter.data;
2507 if (Z_ISUNDEF_P(curobj)) {
2508 ZVAL_NULL(key);
2509 return;
2510 }
2511
2512 php_sxe_object *intern = Z_SXEOBJ_P(curobj);
2513
2514 xmlNodePtr curnode = NULL;
2515 if (intern != NULL && intern->node != NULL) {
2516 curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->node)->node;
2517 }
2518
2519 if (curnode) {
2520 ZVAL_STRINGL(key, (char *) curnode->name, xmlStrlen(curnode->name));
2521 } else {
2522 ZVAL_NULL(key);
2523 }
2524}
2525/* }}} */
2526
2528{
2529 xmlNodePtr node = NULL;
2530 php_sxe_object *intern;
2531
2532 if (!Z_ISUNDEF(sxe->iter.data)) {
2533 intern = Z_SXEOBJ_P(&sxe->iter.data);
2534 GET_NODE(intern, node)
2535 zval_ptr_dtor(&sxe->iter.data);
2536 ZVAL_UNDEF(&sxe->iter.data);
2537 }
2538
2539 if (node) {
2540 php_sxe_iterator_fetch(sxe, node->next, 1);
2541 }
2542}
2543/* }}} */
2544
2545static void php_sxe_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
2546{
2547 php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
2549}
2550/* }}} */
2551
2553{
2554 php_sxe_reset_iterator(sxe);
2555}
2556/* }}} */
2557
2558static void php_sxe_iterator_rewind(zend_object_iterator *iter) /* {{{ */
2559{
2560 php_sxe_object *sxe;
2561
2562 php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
2563 sxe = iterator->sxe;
2564
2565 php_sxe_reset_iterator(sxe);
2566}
2567/* }}} */
2568
2569void *simplexml_export_node(zval *object) /* {{{ */
2570{
2571 php_sxe_object *sxe;
2572 xmlNodePtr node;
2573
2574 sxe = Z_SXEOBJ_P(object);
2575 GET_NODE(sxe, node);
2576 return php_sxe_get_first_node_non_destructive(sxe, node);
2577}
2578/* }}} */
2579
2580/* {{{ Get a simplexml_element object from dom to allow for processing */
2582{
2583 php_sxe_object *sxe;
2584 zval *node;
2585 php_libxml_node_object *object;
2586 xmlNodePtr nodep = NULL;
2588 zend_function *fptr_count;
2589
2590 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|C!", &node, &ce) == FAILURE) {
2591 RETURN_THROWS();
2592 }
2593
2594 nodep = php_libxml_import_node(node);
2595
2596 if (!nodep) {
2597 zend_argument_type_error(1, "must be a valid XML node");
2598 RETURN_THROWS();
2599 }
2600
2601 if (nodep->doc == NULL) {
2602 php_error_docref(NULL, E_WARNING, "Imported Node must have associated Document");
2603 RETURN_NULL();
2604 }
2605
2606 if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
2607 nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
2608 }
2609
2610 if (nodep && nodep->type == XML_ELEMENT_NODE) {
2611 if (!ce) {
2613 fptr_count = NULL;
2614 } else {
2615 fptr_count = php_sxe_find_fptr_count(ce);
2616 }
2617
2618 object = Z_LIBXML_NODE_P(node);
2619
2620 sxe = php_sxe_object_new(ce, fptr_count);
2621 sxe->document = object->document;
2622 php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, nodep->doc);
2623 php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, nodep, NULL);
2624
2625 RETURN_OBJ(&sxe->zo);
2626 } else {
2627 php_error_docref(NULL, E_WARNING, "Invalid Nodetype to import");
2628 RETVAL_NULL();
2629 }
2630}
2631/* }}} */
2632
2633static const zend_module_dep simplexml_deps[] = { /* {{{ */
2634 ZEND_MOD_REQUIRED("libxml")
2635 ZEND_MOD_REQUIRED("spl")
2637};
2638/* }}} */
2639
2642 simplexml_deps,
2643 "SimpleXML",
2644 ext_functions,
2645 PHP_MINIT(simplexml),
2646 PHP_MSHUTDOWN(simplexml),
2647 NULL,
2648 NULL,
2649 PHP_MINFO(simplexml),
2652};
2653/* }}} */
2654
2655#ifdef COMPILE_DL_SIMPLEXML
2656ZEND_GET_MODULE(simplexml)
2657#endif
2658
2659/* {{{ PHP_MINIT_FUNCTION(simplexml) */
2660PHP_MINIT_FUNCTION(simplexml)
2661{
2663 ce_SimpleXMLElement->create_object = sxe_object_new;
2664 ce_SimpleXMLElement->default_object_handlers = &sxe_object_handlers;
2665 ce_SimpleXMLElement->get_iterator = php_sxe_get_iterator;
2666
2667 memcpy(&sxe_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
2668 sxe_object_handlers.offset = XtOffsetOf(php_sxe_object, zo);
2669 sxe_object_handlers.free_obj = sxe_object_free_storage;
2670 sxe_object_handlers.clone_obj = sxe_object_clone;
2671 sxe_object_handlers.read_property = sxe_property_read;
2672 sxe_object_handlers.write_property = sxe_property_write;
2673 sxe_object_handlers.read_dimension = sxe_dimension_read;
2674 sxe_object_handlers.write_dimension = sxe_dimension_write;
2675 sxe_object_handlers.get_property_ptr_ptr = sxe_property_get_adr;
2676 sxe_object_handlers.has_property = sxe_property_exists;
2677 sxe_object_handlers.unset_property = sxe_property_delete;
2678 sxe_object_handlers.has_dimension = sxe_dimension_exists;
2679 sxe_object_handlers.unset_dimension = sxe_dimension_delete;
2680 sxe_object_handlers.get_properties = sxe_get_properties;
2681 sxe_object_handlers.compare = sxe_objects_compare;
2682 sxe_object_handlers.cast_object = sxe_object_cast;
2683 sxe_object_handlers.count_elements = sxe_count_elements;
2684 sxe_object_handlers.get_debug_info = sxe_get_debug_info;
2685 sxe_object_handlers.get_closure = NULL;
2686 sxe_object_handlers.get_gc = sxe_get_gc;
2687
2688 ce_SimpleXMLIterator = register_class_SimpleXMLIterator(ce_SimpleXMLElement);
2689
2690 php_libxml_register_export(ce_SimpleXMLElement, simplexml_export_node);
2691
2692 return SUCCESS;
2693}
2694/* }}} */
2695
2696/* {{{ PHP_MSHUTDOWN_FUNCTION(simplexml) */
2697PHP_MSHUTDOWN_FUNCTION(simplexml)
2698{
2700 return SUCCESS;
2701}
2702/* }}} */
2703
2704/* {{{ PHP_MINFO_FUNCTION(simplexml) */
2705PHP_MINFO_FUNCTION(simplexml)
2706{
2708 php_info_print_table_row(2, "SimpleXML support", "enabled");
2709 php_info_print_table_row(2, "Schema support",
2710#ifdef LIBXML_SCHEMAS_ENABLED
2711 "enabled");
2712#else
2713 "not available");
2714#endif
2716}
2717/* }}} */
2718
2719#endif
rewind($stream)
count(Countable|array $value, int $mode=COUNT_NORMAL)
zend_ffi_type * type
Definition ffi.c:3812
zval * zv
Definition ffi.c:3975
zend_long n
Definition ffi.c:4979
zend_string * res
Definition ffi.c:4692
memcpy(ptr1, ptr2, size)
new_type attr
Definition ffi.c:4364
zend_long offset
zend_string * contents
size_t filename_len
#define NULL
Definition gdcache.h:45
#define prefix
#define SUCCESS
Definition hash_sha3.c:261
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
#define next(ls)
Definition minilua.c:2661
php_info_print_table_start()
Definition info.c:1064
php_info_print_table_row(2, "PDO Driver for Firebird", "enabled")
php_info_print_table_end()
Definition info.c:1074
#define PHP_FUNCTION
Definition php.h:364
#define PHP_MSHUTDOWN_FUNCTION
Definition php.h:401
#define PHP_MINFO
Definition php.h:396
#define PHP_MINIT_FUNCTION
Definition php.h:400
#define PHP_MSHUTDOWN
Definition php.h:393
#define PHP_MINFO_FUNCTION
Definition php.h:404
#define PHP_MINIT
Definition php.h:392
#define PHP_METHOD
Definition php.h:365
const XML_HTML_DOCUMENT_NODE
const XML_PI_NODE
const XML_TEXT_NODE
const XML_ELEMENT_NODE
const XML_ATTRIBUTE_NODE
const XML_DOCUMENT_NODE
const XML_COMMENT_NODE
PHP_JSON_API size_t int options
Definition php_json.h:102
unsigned char key[REFLECTION_KEY_LEN]
#define PHP_SIMPLEXML_VERSION
SXE_ITER
@ SXE_ITER_ELEMENT
@ SXE_ITER_ATTRLIST
@ SXE_ITER_NONE
@ SXE_ITER_CHILD
#define PHP_SXE_API
zend_module_entry simplexml_module_entry
PHP_SXE_API zend_class_entry * ce_SimpleXMLIterator
PHP_SXE_API zend_class_entry * ce_SimpleXMLElement
PHP_SXE_API zend_class_entry * sxe_get_element_class_entry(void)
PHP_SXE_API void php_sxe_move_forward_iterator(php_sxe_object *sxe)
#define SKIP_TEXT(__p)
#define Z_SXEOBJ_P(zv)
PHP_SXE_API zend_object * sxe_object_new(zend_class_entry *ce)
PHP_SXE_API void php_sxe_rewind_iterator(php_sxe_object *sxe)
PHPAPI zend_string * php_trim(zend_string *str, const char *what, size_t what_len, int mode)
Definition string.c:628
zend_constant * data
zval * current
Definition session.c:1024
zval rv
Definition session.c:1024
ptrdiff_t namelen
Definition session.c:1097
simplexml_load_file(string $filename, ?string $class_name=SimpleXMLElement::class, int $options=0, string $namespace_or_prefix="", bool $is_prefix=false)
simplexml_load_string(string $data, ?string $class_name=SimpleXMLElement::class, int $options=0, string $namespace_or_prefix="", bool $is_prefix=false)
simplexml_import_dom(object $node, ?string $class_name=SimpleXMLElement::class)
PHPAPI zend_class_entry * spl_ce_RecursiveIterator
HashTable function_table
Definition zend.h:163
zend_object_write_property_t write_property
zend_object_compare_t compare
zend_object_unset_property_t unset_property
zend_object_unset_dimension_t unset_dimension
zend_object_get_property_ptr_ptr_t get_property_ptr_ptr
zend_object_get_closure_t get_closure
zend_object_free_obj_t free_obj
zend_object_get_debug_info_t get_debug_info
zend_object_get_gc_t get_gc
zend_object_has_dimension_t has_dimension
zend_object_read_property_t read_property
zend_object_cast_t cast_object
zend_object_has_property_t has_property
zend_object_read_dimension_t read_dimension
zend_object_clone_obj_t clone_obj
zend_object_count_elements_t count_elements
zend_object_get_properties_t get_properties
zend_object_write_dimension_t write_dimension
const zend_object_iterator_funcs * funcs
zend_class_entry * ce
Definition zend_types.h:560
Definition file.h:177
zend_object_iterator intern
struct php_sxe_object::@314363337307304257152002232024226372106223326122 iter
zend_function * fptr_count
HashTable * properties
php_libxml_node_ptr * node
zend_string * name
xmlXPathContextPtr xpath
php_libxml_ref_obj * document
zend_string * nsprefix
zend_object zo
test($x, $y=0)
Definition test.php:21
zend_class_entry * scope
struct _zend_function::@236135173067030250234125302313220025134003177336 common
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API ZEND_COLD void zend_type_error(const char *format,...)
Definition zend.c:1824
ZEND_API ZEND_COLD void zend_value_error(const char *format,...)
Definition zend.c:1849
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format,...)
Definition zend_API.c:413
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API void add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value)
Definition zend_API.c:2027
ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type)
Definition zend_API.c:1688
ZEND_API ZEND_COLD void zend_argument_must_not_be_empty_error(uint32_t arg_num)
Definition zend_API.c:443
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:423
#define RETURN_COPY_DEREF(zv)
Definition zend_API.h:1056
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define RETURN_STRINGL(s, l)
Definition zend_API.h:1044
#define RETURN_OBJ(r)
Definition zend_API.h:1052
#define RETURN_FALSE
Definition zend_API.h:1058
#define RETURN_NULL()
Definition zend_API.h:1036
#define ZVAL_STRING(z, s)
Definition zend_API.h:956
#define array_init_size(arg, size)
Definition zend_API.h:538
#define ZEND_GET_MODULE(name)
Definition zend_API.h:241
#define zend_parse_parameters_none()
Definition zend_API.h:353
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETVAL_NULL()
Definition zend_API.h:1010
#define RETVAL_EMPTY_ARRAY()
Definition zend_API.h:1025
#define RETURN_BOOL(b)
Definition zend_API.h:1035
#define RETURN_NEW_STR(s)
Definition zend_API.h:1041
#define RETURN_THROWS()
Definition zend_API.h:1060
#define ZEND_THIS
Definition zend_API.h:523
#define RETURN_EMPTY_STRING()
Definition zend_API.h:1047
#define ZVAL_STRINGL(z, s, l)
Definition zend_API.h:952
#define RETURN_TRUE
Definition zend_API.h:1059
#define array_init(arg)
Definition zend_API.h:537
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
zend_string_release_ex(func->internal_function.function_name, 0)
#define GET_NODE(target, src)
#define BP_VAR_W
#define BP_VAR_RW
#define BP_VAR_IS
#define E_WARNING
Definition zend_errors.h:24
ZEND_API zend_class_entry * zend_ce_exception
ZEND_API ZEND_COLD zend_object * zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code)
union _zend_function zend_function
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_real_init_packed(HashTable *ht)
Definition zend_hash.c:330
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert_new(HashTable *ht, zval *pData)
Definition zend_hash.c:1229
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert(HashTable *ht, zval *pData)
Definition zend_hash.c:1224
ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
Definition zend_hash.c:1869
ZEND_API zval *ZEND_FASTCALL zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData)
Definition zend_hash.c:1007
ZEND_API zval *ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
Definition zend_hash.c:2668
#define zend_new_array(size)
Definition zend_hash.h:338
ZEND_API zend_class_entry * zend_ce_countable
ZEND_API zend_class_entry * zend_ce_stringable
ZEND_API void zend_iterator_init(zend_object_iterator *iter)
struct _zend_object_iterator zend_object_iterator
struct _zend_object_iterator_funcs zend_object_iterator_funcs
int32_t zend_long
Definition zend_long.h:42
#define ZEND_LONG_FMT
Definition zend_long.h:87
struct _zend_string zend_string
#define ZEND_MOD_END
struct _zend_module_dep zend_module_dep
struct _zend_module_entry zend_module_entry
#define STANDARD_MODULE_PROPERTIES
#define ZEND_MOD_REQUIRED(name)
#define STANDARD_MODULE_HEADER_EX
ZEND_API zend_result zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, int type)
ZEND_API const zend_object_handlers std_object_handlers
#define ZEND_COMPARE_OBJECTS_FALLBACK(op1, op2)
ZEND_API void ZEND_FASTCALL zend_object_std_init(zend_object *object, zend_class_entry *ce)
ZEND_API void zend_object_std_dtor(zend_object *object)
ZEND_API zend_string *ZEND_FASTCALL zval_try_get_string_func(zval *op)
ZEND_API void ZEND_FASTCALL convert_to_double(zval *op)
ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op)
ZEND_API void ZEND_FASTCALL convert_to_long(zval *op)
#define ZEND_UNCOMPARABLE
#define convert_to_string(op)
#define ZEND_IGNORE_VALUE(x)
#define ZEND_FALLTHROUGH
#define XtOffsetOf(s_type, field)
#define ZEND_ASSERT(c)
#define UNEXPECTED(condition)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
#define ZEND_SIZE_T_INT_OVFL(size)
#define ZEND_LONG_EXCEEDS_INT(zlong)
ZEND_API zend_string * zend_empty_string
Definition zend_string.c:51
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_KNOWN(idx)
#define ZSTR_EMPTY_ALLOC()
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define ZVAL_STR(z, s)
#define ZVAL_UNDEF(z)
#define IS_FALSE
Definition zend_types.h:602
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
#define Z_ISUNDEF_P(zval_p)
Definition zend_types.h:957
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_TRUE(z)
#define ZVAL_NULL(z)
#define ZVAL_DEREF(z)
#define IS_STRING
Definition zend_types.h:606
struct _zend_array HashTable
Definition zend_types.h:386
#define Z_OBJ_P(zval_p)
Definition zend_types.h:990
#define IS_ARRAY
Definition zend_types.h:607
#define IS_DOUBLE
Definition zend_types.h:605
#define Z_ISUNDEF(zval)
Definition zend_types.h:956
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define Z_STR(zval)
Definition zend_types.h:971
#define GC_FLAGS(p)
Definition zend_types.h:756
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
#define IS_NULL
Definition zend_types.h:601
#define Z_OBJCE_P(zval_p)
#define ZVAL_OBJ(z, o)
@ FAILURE
Definition zend_types.h:61
#define IS_OBJECT
Definition zend_types.h:608
#define IS_LONG
Definition zend_types.h:604
#define ZVAL_ARR(z, a)
#define Z_ARR(zval)
Definition zend_types.h:983
#define _IS_BOOL
Definition zend_types.h:629
#define ZVAL_OBJ_COPY(z, o)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define IS_ARRAY_IMMUTABLE
Definition zend_types.h:823
#define _IS_NUMBER
Definition zend_types.h:630
struct _zend_object_handlers zend_object_handlers
Definition zend_types.h:88
#define Z_ARRVAL(zval)
Definition zend_types.h:986
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
#define ZVAL_COPY_VALUE(z, v)
#define ZVAL_BOOL(z, b)
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zval retval
zval * return_value
zend_string * name
bool result
object
zval * ret
value
out($f, $s)