From 40a3cdd97be87ad6dad215d301b87d4e9d857eca Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Tue, 29 Nov 2005 02:51:07 +0000 Subject: [PATCH] - MFH . Fix memleaks . Add tests . Add functions: getNamespaces(), getDocNamespaces() . Fixed var_dump() . Fixed bugs: #35028 XML object fails FALSE test # This plan was decided before 5.1.0 came out with ilia and checked again # just now. The extension currently shows no more memleaks or errors using # the test suite. --- ext/simplexml/simplexml.c | 563 +++++++++++++----- ext/simplexml/tests/000.phpt | 254 ++++++++ ext/simplexml/tests/000.xml | 16 + ext/simplexml/tests/001.phpt | 68 +-- ext/simplexml/tests/002.phpt | 68 ++- ext/simplexml/tests/003.phpt | 80 +-- ext/simplexml/tests/004.phpt | 63 +- ext/simplexml/tests/005.phpt | 2 +- ext/simplexml/tests/006.phpt | 2 +- ext/simplexml/tests/007.phpt | 9 +- ext/simplexml/tests/008.phpt | 2 +- ext/simplexml/tests/009.phpt | 4 +- ext/simplexml/tests/010.phpt | 63 +- ext/simplexml/tests/011.phpt | 2 +- ext/simplexml/tests/012.phpt | 3 +- ext/simplexml/tests/013.phpt | 2 +- ext/simplexml/tests/014a.phpt | 2 +- ext/simplexml/tests/014b.phpt | 2 +- ext/simplexml/tests/019.phpt | 2 +- ext/simplexml/tests/020.phpt | 2 +- ext/simplexml/tests/021.phpt | 2 +- ext/simplexml/tests/022.phpt | 36 +- ext/simplexml/tests/023.phpt | 7 +- ext/simplexml/tests/024.phpt | 175 ++++++ ext/simplexml/tests/025.phpt | 92 +++ ext/simplexml/tests/bug27010.phpt | 2 +- ext/simplexml/tests/profile11.phpt | 31 +- ext/simplexml/tests/simplexml_import_dom.phpt | 2 +- 28 files changed, 1213 insertions(+), 343 deletions(-) create mode 100755 ext/simplexml/tests/000.phpt create mode 100755 ext/simplexml/tests/000.xml create mode 100755 ext/simplexml/tests/024.phpt create mode 100755 ext/simplexml/tests/025.phpt diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 985343bbce..310f3718d3 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -38,6 +38,8 @@ #include "ext/spl/spl_sxe.h" #endif +#define SXE_ELEMENT_BY_NAME 0 + zend_class_entry *sxe_class_entry = NULL; ZEND_API zend_class_entry *sxe_get_element_class_entry() @@ -51,8 +53,8 @@ ZEND_API zend_class_entry *sxe_get_element_class_entry() static php_sxe_object* php_sxe_object_new(zend_class_entry *ce TSRMLS_DC); static zend_object_value php_sxe_register_object(php_sxe_object * TSRMLS_DC); -static void php_sxe_reset_iterator(php_sxe_object *sxe TSRMLS_DC); -static void php_sxe_move_forward_iterator(php_sxe_object *sxe TSRMLS_DC); +static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data TSRMLS_DC); +static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data TSRMLS_DC); /* {{{ _node_as_zval() */ @@ -103,7 +105,7 @@ static xmlNodePtr php_sxe_get_first_node(php_sxe_object *sxe, xmlNodePtr node TS xmlNodePtr retnode = NULL; if (sxe && sxe->iter.type != SXE_ITER_NONE) { - php_sxe_reset_iterator(sxe TSRMLS_CC); + php_sxe_reset_iterator(sxe, 1 TSRMLS_CC); if (sxe->iter.data) { intern = (php_sxe_object *)zend_object_store_get_object(sxe->iter.data TSRMLS_CC); GET_NODE(intern, retnode) @@ -114,10 +116,7 @@ static xmlNodePtr php_sxe_get_first_node(php_sxe_object *sxe, xmlNodePtr node TS } } -/* {{{ match_ns() - */ -static inline int -match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name) +static inline int match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name) /* {{{ */ { if (name == NULL && (node->ns == NULL || node->ns->prefix == NULL)) { return 1; @@ -131,9 +130,8 @@ match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name) } /* }}} */ -/* {{{ sxe_get_element_node() - */ -static xmlNodePtr sxe_get_element_by_offset(php_sxe_object *sxe, long offset, xmlNodePtr node) { +static xmlNodePtr sxe_get_element_by_offset(php_sxe_object *sxe, long offset, xmlNodePtr node) /* {{{ */ +{ long nodendx = 0; if (sxe->iter.type == SXE_ITER_NONE) { @@ -158,6 +156,71 @@ next_iter: } /* }}} */ +#if SXE_ELEMENT_BY_NAME +static xmlNodePtr sxe_find_element_by_name(php_sxe_object *sxe, xmlNodePtr node, char *name TSRMLS_DC) /* {{{ */ +{ + while (node) { + SKIP_TEXT(node) + if (node->type == XML_ELEMENT_NODE && match_ns(sxe, node, sxe->iter.nsprefix)) { + if (!xmlStrcmp(node->name, name)) { + return node; + } + } +next_iter: + node = node->next; + } + return NULL; +} /* }}} */ + +static xmlNodePtr sxe_get_element_by_name(php_sxe_object *sxe, xmlNodePtr node, char **name, int *type TSRMLS_DC) /* {{{ */ +{ + int orgtype; + xmlNodePtr orgnode = node; + xmlNodePtr retnode = NULL; + + if (sxe->iter.type != SXE_ITER_ATTRLIST) + { + orgtype = sxe->iter.type; + if (sxe->iter.type == SXE_ITER_NONE) { + sxe->iter.type = SXE_ITER_CHILD; + } + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + sxe->iter.type = orgtype; + } + + if (sxe->iter.type == SXE_ITER_ELEMENT) { + orgnode = sxe_find_element_by_name(sxe, node, sxe->iter.name TSRMLS_CC); + node = orgnode->children; + } + + while (node) { + SKIP_TEXT(node) + if (node->type == XML_ELEMENT_NODE && match_ns(sxe, node, sxe->iter.nsprefix)) { + if (!xmlStrcmp(node->name, *name)) { + if (1||retnode) + { + *type = SXE_ITER_ELEMENT; + return orgnode; + } + retnode = node; + } + } +next_iter: + node = node->next; + } + + if (retnode) + { + *type = SXE_ITER_NONE; + *name = NULL; + return retnode; + } + + return NULL; +} +/* }}} */ +#endif /* SXE_ELEMENT_BY_NAME */ + /* {{{ sxe_prop_dim_read() */ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements, zend_bool attribs, zend_bool silent TSRMLS_DC) @@ -169,6 +232,7 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements, xmlAttrPtr attr; zval tmp_zv; int nodendx = 0; + int test; sxe = php_sxe_fetch_object(object TSRMLS_CC); @@ -177,6 +241,7 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements, attribs = 0; elements = 1; } + name = NULL; } else { if (Z_TYPE_P(member) != IS_STRING) { tmp_zv = *member; @@ -184,28 +249,32 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements, member = &tmp_zv; convert_to_string(member); } + name = Z_STRVAL_P(member); } MAKE_STD_ZVAL(return_value); ZVAL_NULL(return_value); - name = Z_STRVAL_P(member); - GET_NODE(sxe, node); - if (sxe->iter.type != SXE_ITER_CHILD && sxe->iter.type != SXE_ITER_ATTRLIST) { + if (sxe->iter.type == SXE_ITER_ATTRLIST) { + attribs = 1; + elements = 0; + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + attr = (xmlAttrPtr)node; + test = sxe->iter.name != NULL; + } else if (sxe->iter.type != SXE_ITER_CHILD) { node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + attr = node ? node->properties : NULL; + test = 0; } if (node) { if (attribs) { - if (Z_TYPE_P(member) == IS_LONG && sxe->iter.type != SXE_ITER_ATTRLIST) { - attr = NULL; - } else { - attr = node->properties; + if (Z_TYPE_P(member) != IS_LONG || sxe->iter.type == SXE_ITER_ATTRLIST) { if (Z_TYPE_P(member) == IS_LONG) { while (attr && nodendx <= Z_LVAL_P(member)) { - if (match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { if (nodendx == Z_LVAL_P(member)) { _node_as_zval(sxe, (xmlNodePtr) attr, return_value, SXE_ITER_NONE, NULL, sxe->iter.nsprefix TSRMLS_CC); break; @@ -216,7 +285,7 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements, } } else { while (attr) { - if (!xmlStrcmp(attr->name, name) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, name) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { _node_as_zval(sxe, (xmlNodePtr) attr, return_value, SXE_ITER_NONE, NULL, sxe->iter.nsprefix TSRMLS_CC); break; } @@ -239,7 +308,17 @@ static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements, _node_as_zval(sxe, node, return_value, SXE_ITER_NONE, NULL, sxe->iter.nsprefix TSRMLS_CC); } } else { +#if SXE_ELEMENT_BY_NAME + int newtype; + + GET_NODE(sxe, node); + node = sxe_get_element_by_name(sxe, node, &name, &newtype TSRMLS_CC); + if (node) { + _node_as_zval(sxe, node, return_value, newtype, name, sxe->iter.nsprefix TSRMLS_CC); + } +#else _node_as_zval(sxe, node, return_value, SXE_ITER_ELEMENT, name, sxe->iter.nsprefix TSRMLS_CC); +#endif } } } @@ -315,6 +394,7 @@ static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_boo int counter = 0; int is_attr = 0; int nodendx = 0; + int test; zval tmp_zv, trim_zv; if (!member) { @@ -357,16 +437,23 @@ static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_boo GET_NODE(sxe, node); - if (sxe->iter.type != SXE_ITER_ATTRLIST) { + if (sxe->iter.type == SXE_ITER_ATTRLIST) { + attribs = 1; + elements = 0; node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + attr = (xmlAttrPtr)node; + test = sxe->iter.name != NULL; + } else if (sxe->iter.type != SXE_ITER_CHILD) { + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + attr = node ? node->properties : NULL; + test = 0; } if (node) { if (attribs) { - attr = node->properties; if (Z_TYPE_P(member) == IS_LONG) { while (attr && nodendx <= Z_LVAL_P(member)) { - if (match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { if (nodendx == Z_LVAL_P(member)) { is_attr = 1; ++counter; @@ -378,7 +465,7 @@ static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_boo } } else { while (attr) { - if (!xmlStrcmp(attr->name, name) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, name) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { is_attr = 1; ++counter; break; @@ -471,6 +558,7 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend xmlNodePtr node; xmlAttrPtr attr = NULL; int exists = 0; + int test; sxe = php_sxe_fetch_object(object TSRMLS_CC); @@ -488,15 +576,22 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend } } - if (sxe->iter.type != SXE_ITER_CHILD && sxe->iter.type != SXE_ITER_ATTRLIST) { + if (sxe->iter.type == SXE_ITER_ATTRLIST) { + attribs = 1; + elements = 0; + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + attr = (xmlAttrPtr)node; + test = sxe->iter.name != NULL; + } else if (sxe->iter.type != SXE_ITER_CHILD) { node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + attr = node ? node->properties : NULL; + test = 0; } if (node) { if (attribs) { - attr = node->properties; while (attr) { - if (!xmlStrcmp(attr->name, name) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, name) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { exists = 1; break; } @@ -513,8 +608,10 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node); } else { + zval tmp_zv; + if (Z_TYPE_P(member) != IS_STRING) { - zval tmp_zv = *member; + tmp_zv = *member; zval_copy_ctor(&tmp_zv); member = &tmp_zv; convert_to_string(member); @@ -528,6 +625,9 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend } node = nnext; } + if (member == &tmp_zv) { + zval_dtor(&tmp_zv); + } } if (node) { exists = 1; @@ -565,6 +665,7 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements, xmlAttrPtr attr; xmlAttrPtr anext; zval tmp_zv; + int test; if (Z_TYPE_P(member) != IS_STRING) { tmp_zv = *member; @@ -576,14 +677,23 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements, sxe = php_sxe_fetch_object(object TSRMLS_CC); GET_NODE(sxe, node); + if (sxe->iter.type == SXE_ITER_ATTRLIST) { + attribs = 1; + elements = 0; node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + attr = (xmlAttrPtr)node; + test = sxe->iter.name != NULL; + } else { + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + attr = node ? node->properties : NULL; + test = 0; + } if (node) { if (attribs) { - attr = node->properties; while (attr) { anext = attr->next; - if (!xmlStrcmp(attr->name, Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { xmlUnlinkNode((xmlNodePtr) attr); php_libxml_node_free_resource((xmlNodePtr) attr TSRMLS_CC); break; @@ -632,10 +742,19 @@ static void sxe_dimension_delete(zval *object, zval *offset TSRMLS_DC) } /* }}} */ +static inline char * sxe_xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) +{ + xmlChar *tmp = xmlNodeListGetString(doc, list, inLine); + char *res = estrdup((char*)tmp); + + xmlFree(tmp); + + return res; +} + /* {{{ _get_base_node_value() */ -static void -_get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval **value, char *prefix TSRMLS_DC) +static void _get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval **value, char *prefix TSRMLS_DC) { php_sxe_object *subnode; xmlChar *contents; @@ -656,6 +775,7 @@ _get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval **value, cha subnode->iter.nsprefix = xmlStrdup(prefix); } php_libxml_increment_node_ptr((php_libxml_node_object *)subnode, node, NULL TSRMLS_CC); + (*value)->type = IS_OBJECT; (*value)->value.obj = php_sxe_register_object(subnode TSRMLS_CC); /*zval_add_ref(value);*/ @@ -663,20 +783,43 @@ _get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval **value, cha } /* }}} */ +static void sxe_properties_add(HashTable *rv, char *name, int namelen, zval *value TSRMLS_DC) +{ + zval **data_ptr; + zval *newptr; + ulong h = zend_hash_func(name, namelen); + + if (zend_hash_quick_find(rv, name, namelen, h, (void **) &data_ptr) == SUCCESS) { + if (Z_TYPE_PP(data_ptr) == IS_ARRAY) { + zend_hash_next_index_insert(Z_ARRVAL_PP(data_ptr), &value, sizeof(zval *), NULL); + } else { + MAKE_STD_ZVAL(newptr); + array_init(newptr); + + zval_add_ref(data_ptr); + zend_hash_next_index_insert(Z_ARRVAL_P(newptr), data_ptr, sizeof(zval *), NULL); + zend_hash_next_index_insert(Z_ARRVAL_P(newptr), &value, sizeof(zval *), NULL); + + zend_hash_quick_update(rv, name, namelen, h, &newptr, sizeof(zval *), NULL); + } + } else { + zend_hash_quick_update(rv, name, namelen, h, &value, sizeof(zval *), NULL); + } +} + /* {{{ sxe_properties_get() */ -static HashTable * -sxe_properties_get(zval *object TSRMLS_DC) +static HashTable * sxe_properties_get(zval *object TSRMLS_DC) { - zval **data_ptr; zval *value; - zval *newptr; + zval *zattr; HashTable *rv; php_sxe_object *sxe; char *name; xmlNodePtr node; - ulong h; + xmlAttrPtr attr; int namelen; + int test; sxe = php_sxe_fetch_object(object TSRMLS_CC); @@ -689,24 +832,49 @@ sxe_properties_get(zval *object TSRMLS_DC) sxe->properties = rv; } + GET_NODE(sxe, node); + if (1||sxe->iter.type != SXE_ITER_CHILD) { + if (sxe->iter.type == SXE_ITER_ELEMENT) { + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + } + attr = node ? (xmlAttrPtr)node->properties : NULL; + zattr = NULL; + test = sxe->iter.name && sxe->iter.type == SXE_ITER_ATTRLIST; + while (attr) { + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr)attr, sxe->iter.nsprefix)) { + MAKE_STD_ZVAL(value); + ZVAL_STRING(value, sxe_xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, attr->children, 1), 0); + namelen = xmlStrlen(attr->name) + 1; + if (!zattr) { + MAKE_STD_ZVAL(zattr); + array_init(zattr); + sxe_properties_add(rv, "@attributes", sizeof("@attributes"), zattr TSRMLS_CC); + } + add_assoc_zval_ex(zattr, (char*)attr->name, namelen, value); + } + attr = attr->next; + } + } + GET_NODE(sxe, node); node = php_sxe_get_first_node(sxe, node TSRMLS_CC); if (node && sxe->iter.type != SXE_ITER_ATTRLIST) { if (node->type == XML_ATTRIBUTE_NODE) { MAKE_STD_ZVAL(value); - ZVAL_STRING(value, xmlNodeListGetString(node->doc, node->children, 1), 1); + ZVAL_STRING(value, sxe_xmlNodeListGetString(node->doc, node->children, 1), 0); zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL); node = NULL; } else { node = node->children; } + while (node) { if (node->children != NULL || node->prev != NULL || node->next != NULL) { SKIP_TEXT(node); } else { if (node->type == XML_TEXT_NODE) { MAKE_STD_ZVAL(value); - ZVAL_STRING(value, xmlNodeListGetString(node->doc, node, 1), 1); + ZVAL_STRING(value, sxe_xmlNodeListGetString(node->doc, node, 1), 0); zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL); goto next_iter; } @@ -725,24 +893,7 @@ sxe_properties_get(zval *object TSRMLS_DC) _get_base_node_value(sxe, node, &value, sxe->iter.nsprefix TSRMLS_CC); - h = zend_hash_func(name, namelen); - if (zend_hash_quick_find(rv, name, namelen, h, (void **) &data_ptr) == SUCCESS) { - if (Z_TYPE_PP(data_ptr) == IS_ARRAY) { - zend_hash_next_index_insert(Z_ARRVAL_PP(data_ptr), &value, sizeof(zval *), NULL); - } else { - MAKE_STD_ZVAL(newptr); - array_init(newptr); - - zval_add_ref(data_ptr); - zend_hash_next_index_insert(Z_ARRVAL_P(newptr), data_ptr, sizeof(zval *), NULL); - zend_hash_next_index_insert(Z_ARRVAL_P(newptr), &value, sizeof(zval *), NULL); - - zend_hash_quick_update(rv, name, namelen, h, &newptr, sizeof(zval *), NULL); - } - } else { - zend_hash_quick_update(rv, name, namelen, h, &value, sizeof(zval *), NULL); - } - + sxe_properties_add(rv, name, namelen, value TSRMLS_CC); next_iter: node = node->next; } @@ -752,10 +903,7 @@ next_iter: } /* }}} */ -/* {{{ sxe_objects_compare() - */ -static int -sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC) +static int sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC) /* {{{ */ { php_sxe_object *sxe1; php_sxe_object *sxe2; @@ -796,6 +944,11 @@ SXE_METHOD(xpath) } sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + + if (sxe->iter.type == SXE_ITER_ATTRLIST) { + return; /* attributes don't have attributes */ + } + if (!sxe->xpath) { sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr); } @@ -845,6 +998,8 @@ SXE_METHOD(xpath) */ if (nodeptr->type == XML_TEXT_NODE) { _node_as_zval(sxe, nodeptr->parent, value, SXE_ITER_NONE, NULL, NULL TSRMLS_CC); + } else if (nodeptr->type == XML_ATTRIBUTE_NODE) { + _node_as_zval(sxe, nodeptr->parent, value, SXE_ITER_ATTRLIST, (char*)nodeptr->name, NULL TSRMLS_CC); } else { _node_as_zval(sxe, nodeptr, value, SXE_ITER_NONE, NULL, NULL TSRMLS_CC); } @@ -952,6 +1107,114 @@ SXE_METHOD(asXML) } /* }}} */ +#define SXE_NS_PREFIX(ns) (ns->prefix ? (char*)ns->prefix : "") + +static inline void sxe_add_namespace_name(zval *return_value, xmlNsPtr ns) +{ + char *prefix = SXE_NS_PREFIX(ns); + if (zend_hash_exists(Z_ARRVAL_P(return_value), prefix, strlen(prefix) + 1) == 0) { + add_assoc_string(return_value, prefix, (char*)ns->href, 1); + } +} + +static void sxe_add_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool recursive, zval *return_value TSRMLS_DC) /* {{{ */ +{ + xmlAttrPtr attr; + + if (node->ns) { + sxe_add_namespace_name(return_value, node->ns); + } + + attr = node->properties; + while (attr) { + if (attr->ns) { + sxe_add_namespace_name(return_value, attr->ns); + } + attr = attr->next; + } + + if (recursive) { + node = node->children; + while (node) { + if (node->type == XML_ELEMENT_NODE) { + sxe_add_namespaces(sxe, node, recursive, return_value TSRMLS_CC); + } + node = node->next; + } + } +} /* }}} */ + +/* {{{ proto string SimpleXMLElement::getNamespaces([bool recursve]) + Return all namespaces in use */ +SXE_METHOD(getNamespaces) +{ + zend_bool recursive = 0; + php_sxe_object *sxe; + xmlNodePtr node; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &recursive) == FAILURE) { + return; + } + + array_init(return_value); + + sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + GET_NODE(sxe, node); + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + + while (node) { + SKIP_TEXT(node) + if (node->type == XML_ELEMENT_NODE) { + sxe_add_namespaces(sxe, node, recursive, return_value TSRMLS_CC); + } else if (node->type == XML_ATTRIBUTE_NODE && node->ns) { + sxe_add_namespace_name(return_value, node->ns); + } +next_iter: + node = node->next; + } +} +/* }}} */ + +static void sxe_add_registered_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool recursive, zval *return_value TSRMLS_DC) /* {{{ */ +{ + xmlNsPtr ns; + + if (node->type == XML_ELEMENT_NODE) { + ns = node->nsDef; + while (ns != NULL) { + sxe_add_namespace_name(return_value, ns); + ns = ns->next; + } + if (recursive) { + node = node->children; + while (node) { + sxe_add_registered_namespaces(sxe, node, recursive, return_value TSRMLS_CC); + node = node->next; + } + } + } +} +/* }}} */ + +/* {{{ proto string SimpleXMLElement::getDocNamespaces([bool recursive]) + Return all namespaces registered with document */ +SXE_METHOD(getDocNamespaces) +{ + zend_bool recursive = 0; + php_sxe_object *sxe; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &recursive) == FAILURE) { + return; + } + + array_init(return_value); + + sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + + sxe_add_registered_namespaces(sxe, xmlDocGetRootElement((xmlDocPtr)sxe->document->ptr), recursive, return_value TSRMLS_CC); +} +/* }}} */ + /* {{{ proto object SimpleXMLElement::children() Finds children of given node */ SXE_METHOD(children) @@ -966,6 +1229,11 @@ SXE_METHOD(children) } sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + + if (sxe->iter.type == SXE_ITER_ATTRLIST) { + return; /* attributes don't have attributes */ + } + GET_NODE(sxe, node); node = php_sxe_get_first_node(sxe, node TSRMLS_CC); @@ -989,6 +1257,11 @@ SXE_METHOD(attributes) sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); GET_NODE(sxe, node); + + if (sxe->iter.type == SXE_ITER_ATTRLIST) { + return; /* attributes don't have attributes */ + } + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); _node_as_zval(sxe, node, return_value, SXE_ITER_ATTRLIST, NULL, nsprefix TSRMLS_CC); @@ -997,8 +1270,7 @@ SXE_METHOD(attributes) /* {{{ cast_object() */ -static int -cast_object(zval *object, int type, char *contents TSRMLS_DC) +static int cast_object(zval *object, int type, char *contents TSRMLS_DC) { if (contents) { ZVAL_STRINGL(object, contents, strlen(contents), 1); @@ -1030,19 +1302,24 @@ cast_object(zval *object, int type, char *contents TSRMLS_DC) /* {{{ sxe_object_cast() */ -static int -sxe_object_cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC) +static int sxe_object_cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC) { php_sxe_object *sxe; char *contents = NULL; xmlNodePtr node; - zval free_obj; - int rv; + int rv, empty; sxe = php_sxe_fetch_object(readobj TSRMLS_CC); - if (should_free) { - free_obj = *writeobj; + if (type == IS_BOOL) { + node = php_sxe_get_first_node(sxe, NULL TSRMLS_CC); + empty = node == NULL && zend_hash_num_elements(sxe_properties_get(readobj TSRMLS_CC)) == 0; + if (should_free) { + zval_dtor(readobj); + } + INIT_PZVAL(writeobj); + ZVAL_BOOL(writeobj, !empty); + return SUCCESS; } if (sxe->iter.type != SXE_ITER_NONE) { @@ -1064,18 +1341,39 @@ sxe_object_cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_ } } + if (should_free) { + zval_dtor(readobj); + } + rv = cast_object(writeobj, type, contents TSRMLS_CC); if (contents) { xmlFree(contents); } - if (should_free) { - zval_dtor(&free_obj); - } return rv; } /* }}} */ +static int sxe_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */ +{ + php_sxe_object *sxe; + xmlNodePtr node; + + *count = 0; + sxe = php_sxe_fetch_object(object TSRMLS_CC); + node = php_sxe_reset_iterator(sxe, 0 TSRMLS_CC); + + while (node) + { + (*count)++; + node = php_sxe_iterator_fetch(sxe, node->next, 0 TSRMLS_CC); + } + + + return SUCCESS; +} +/* }}} */ + static zval *sxe_get_value(zval *z TSRMLS_DC) { zval *retval; @@ -1084,6 +1382,7 @@ static zval *sxe_get_value(zval *z TSRMLS_DC) if (sxe_object_cast(z, retval, IS_STRING, 0 TSRMLS_CC)==FAILURE) { zend_error(E_ERROR, "Unable to cast node to string"); + /* FIXME: Should not be fatal */ } retval->refcount = 0; @@ -1112,7 +1411,7 @@ static zend_object_handlers sxe_object_handlers = { NULL, /* zend_get_std_object_handlers()->get_class_name,*/ sxe_objects_compare, sxe_object_cast, - NULL + sxe_count_elements }; static zend_object_handlers sxe_ze1_object_handlers = { @@ -1136,13 +1435,14 @@ static zend_object_handlers sxe_ze1_object_handlers = { NULL, /* zend_get_std_object_handlers()->get_class_name,*/ sxe_objects_compare, sxe_object_cast, - NULL + sxe_count_elements }; static zend_object_value sxe_object_ze1_clone(zval *zobject TSRMLS_DC) { php_error(E_ERROR, "Cannot clone object of class %s due to 'zend.ze1_compatibility_mode'", Z_OBJCE_P(zobject)->name); /* Return zobject->value.obj just to satisfy compiler */ + /* FIXME: Should not be a fatal */ return zobject->value.obj; } @@ -1363,7 +1663,7 @@ PHP_FUNCTION(simplexml_load_string) /* }}} */ -/* {{{ proto SimpleXMLElement::__construct(string data) +/* {{{ proto SimpleXMLElement::__construct(string data [, int options [, bool data_is_url]]) SimpleXMLElement constructor */ SXE_METHOD(__construct) { @@ -1371,15 +1671,21 @@ SXE_METHOD(__construct) char *data; int data_len; xmlDocPtr docp; + long options = 0; + zend_bool is_url = 0; php_set_error_handling(EH_THROW, zend_exception_get_default() TSRMLS_CC); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &data, &data_len, &options, &is_url) == FAILURE) { php_std_error_handling(); return; } php_std_error_handling(); - docp = xmlParseMemory(data, data_len); +#if LIBXML_VERSION >= 20600 + docp = is_url ? xmlReadFile(data, NULL, options) : xmlReadMemory(data, data_len, NULL, NULL, options); +#else + docp = is_url ? xmlParseFile(data) : xmlParseMemory(data, data_len); +#endif if (!docp) { ((php_libxml_node_object *)sxe)->document = NULL; zend_throw_exception(zend_exception_get_default(), "String could not be parsed as XML", 0 TSRMLS_CC); @@ -1408,10 +1714,38 @@ zend_object_iterator_funcs php_sxe_iterator_funcs = { php_sxe_iterator_rewind, }; -static void php_sxe_reset_iterator(php_sxe_object *sxe TSRMLS_DC) +static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data TSRMLS_DC) +{ + char *prefix = sxe->iter.nsprefix; + int test_elem = sxe->iter.type == SXE_ITER_ELEMENT && sxe->iter.name; + int test_attr = sxe->iter.type == SXE_ITER_ATTRLIST && sxe->iter.name; + + while (node) { + SKIP_TEXT(node); + if (sxe->iter.type != SXE_ITER_ATTRLIST && node->type == XML_ELEMENT_NODE) { + if ((!test_elem || !xmlStrcmp(node->name, sxe->iter.name)) && match_ns(sxe, node, prefix)) { + break; + } + } else if (node->type == XML_ATTRIBUTE_NODE) { + if ((!test_attr || !xmlStrcmp(node->name, sxe->iter.name)) && match_ns(sxe, node, prefix)) { + break; + } + } +next_iter: + node = node->next; + } + + if (node && use_data) { + ALLOC_INIT_ZVAL(sxe->iter.data); + _node_as_zval(sxe, node, sxe->iter.data, SXE_ITER_NONE, NULL, sxe->iter.nsprefix TSRMLS_CC); + } + + return node; +} + +static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data TSRMLS_DC) { xmlNodePtr node; - char *prefix; if (sxe->iter.data) { zval_ptr_dtor(&sxe->iter.data); @@ -1430,37 +1764,9 @@ static void php_sxe_reset_iterator(php_sxe_object *sxe TSRMLS_DC) case SXE_ITER_ATTRLIST: node = (xmlNodePtr) node->properties; } + return php_sxe_iterator_fetch(sxe, node, use_data TSRMLS_CC); } - - prefix = sxe->iter.nsprefix; - - while (node) { - SKIP_TEXT(node); - if (sxe->iter.type != SXE_ITER_ATTRLIST && node->type == XML_ELEMENT_NODE) { - if (sxe->iter.type == SXE_ITER_ELEMENT) { - if (!xmlStrcmp(node->name, sxe->iter.name) && match_ns(sxe, node, prefix)) { - break; - } - } else { - if (match_ns(sxe, node, prefix)) { - break; - } - } - } else { - if (node->type == XML_ATTRIBUTE_NODE) { - if (match_ns(sxe, node, sxe->iter.nsprefix)) { - break; - } - } - } -next_iter: - node = node->next; - } - - if (node) { - ALLOC_INIT_ZVAL(sxe->iter.data); - _node_as_zval(sxe, node, sxe->iter.data, SXE_ITER_NONE, NULL, sxe->iter.nsprefix TSRMLS_CC); - } + return NULL; } zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object TSRMLS_DC) @@ -1523,11 +1829,10 @@ static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_k } -static void php_sxe_move_forward_iterator(php_sxe_object *sxe TSRMLS_DC) +ZEND_API void php_sxe_move_forward_iterator(php_sxe_object *sxe TSRMLS_DC) { xmlNodePtr node = NULL; php_sxe_object *intern; - char *prefix; if (sxe->iter.data) { intern = (php_sxe_object *)zend_object_store_get_object(sxe->iter.data TSRMLS_CC); @@ -1537,38 +1842,7 @@ static void php_sxe_move_forward_iterator(php_sxe_object *sxe TSRMLS_DC) } if (node) { - node = node->next; - } - - prefix = sxe->iter.nsprefix; - - while (node) { - SKIP_TEXT(node); - - if (sxe->iter.type != SXE_ITER_ATTRLIST && node->type == XML_ELEMENT_NODE) { - if (sxe->iter.type == SXE_ITER_ELEMENT) { - if (!xmlStrcmp(node->name, sxe->iter.name) && match_ns(sxe, node, prefix)) { - break; - } - } else { - if (match_ns(sxe, node, prefix)) { - break; - } - } - } else { - if (node->type == XML_ATTRIBUTE_NODE) { - if (match_ns(sxe, node, sxe->iter.nsprefix)) { - break; - } - } - } -next_iter: - node = node->next; - } - - if (node) { - ALLOC_INIT_ZVAL(sxe->iter.data); - _node_as_zval(sxe, node, sxe->iter.data, SXE_ITER_NONE, NULL, sxe->iter.nsprefix TSRMLS_CC); + php_sxe_iterator_fetch(sxe, node->next, 1 TSRMLS_CC); } } @@ -1585,10 +1859,9 @@ static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC) php_sxe_iterator *iterator = (php_sxe_iterator *)iter; sxe = iterator->sxe; - php_sxe_reset_iterator(sxe TSRMLS_CC); + php_sxe_reset_iterator(sxe, 1 TSRMLS_CC); } - void *simplexml_export_node(zval *object TSRMLS_DC) { php_sxe_object *sxe; @@ -1691,6 +1964,8 @@ static zend_function_entry sxe_functions[] = { SXE_ME(registerXPathNamespace, NULL, ZEND_ACC_PUBLIC) SXE_ME(attributes, NULL, ZEND_ACC_PUBLIC) SXE_ME(children, NULL, ZEND_ACC_PUBLIC) + SXE_ME(getNamespaces, NULL, ZEND_ACC_PUBLIC) + SXE_ME(getDocNamespaces, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; diff --git a/ext/simplexml/tests/000.phpt b/ext/simplexml/tests/000.phpt new file mode 100755 index 0000000000..51dbe3b5ec --- /dev/null +++ b/ext/simplexml/tests/000.phpt @@ -0,0 +1,254 @@ +--TEST-- +SimpleXML: var_dump() +--SKIPIF-- + +--FILE-- +elem1'); +test('sxe->elem1[0]'); +test('sxe->elem1[0]->elem2'); +test('sxe->elem1[0]->elem2->bla'); +if (!ini_get("unicode_semantics")) test('sxe->elem1[0]["attr1"]'); +test('sxe->elem1[0]->attr1'); +test('sxe->elem1[1]'); +test('sxe->elem1[2]'); +test('sxe->elem11'); +test('sxe->elem11->elem111'); +test('sxe->elem11->elem111->elem1111'); +test('sxe->elem22'); +test('sxe->elem22->elem222'); +test('sxe->elem22->attr22'); +test('sxe->elem22["attr22"]'); + +?> +===DONE=== + +--EXPECTF-- +===sxe +bool(true) +bool(true) +int(3) +object(SimpleXMLElement)#%d (3) { + ["@attributes"]=> + array(1) { + ["id"]=> + string(3) "123" + } + ["elem1"]=> + array(2) { + [0]=> + string(36) "There is some text.Here is some more" + [1]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(2) { + ["attr1"]=> + string(2) "11" + ["attr2"]=> + string(2) "12" + } + } + } + ["elem11"]=> + object(SimpleXMLElement)#%d (1) { + ["elem111"]=> + object(SimpleXMLElement)#%d (1) { + ["elem1111"]=> + object(SimpleXMLElement)#%d (0) { + } + } + } +} +===sxe->elem1 +bool(true) +bool(true) +int(2) +object(SimpleXMLElement)#%d (3) { + ["@attributes"]=> + array(2) { + ["attr1"]=> + string(5) "first" + ["attr2"]=> + string(6) "second" + } + ["comment"]=> + object(SimpleXMLElement)#%d (0) { + } + ["elem2"]=> + object(SimpleXMLElement)#%d (2) { + ["@attributes"]=> + array(2) { + ["att25"]=> + string(2) "25" + ["att42"]=> + string(2) "42" + } + ["elem3"]=> + object(SimpleXMLElement)#%d (1) { + ["elem4"]=> + object(SimpleXMLElement)#%d (1) { + ["test"]=> + object(SimpleXMLElement)#%d (0) { + } + } + } + } +} +===sxe->elem1[0] +bool(true) +bool(true) +int(1) +object(SimpleXMLElement)#%d (3) { + ["@attributes"]=> + array(2) { + ["attr1"]=> + string(5) "first" + ["attr2"]=> + string(6) "second" + } + ["comment"]=> + object(SimpleXMLElement)#%d (0) { + } + ["elem2"]=> + object(SimpleXMLElement)#%d (2) { + ["@attributes"]=> + array(2) { + ["att25"]=> + string(2) "25" + ["att42"]=> + string(2) "42" + } + ["elem3"]=> + object(SimpleXMLElement)#%d (1) { + ["elem4"]=> + object(SimpleXMLElement)#%d (1) { + ["test"]=> + object(SimpleXMLElement)#%d (0) { + } + } + } + } +} +===sxe->elem1[0]->elem2 +bool(true) +bool(true) +int(1) +object(SimpleXMLElement)#%d (2) { + ["@attributes"]=> + array(2) { + ["att25"]=> + string(2) "25" + ["att42"]=> + string(2) "42" + } + ["elem3"]=> + object(SimpleXMLElement)#%d (1) { + ["elem4"]=> + object(SimpleXMLElement)#%d (1) { + ["test"]=> + object(SimpleXMLElement)#%d (0) { + } + } + } +} +===sxe->elem1[0]->elem2->bla +bool(false) +bool(false) +int(0) +object(SimpleXMLElement)#%d (0) { +} +===sxe->elem1[0]["attr1"] +bool(true) +bool(true) +int(0) +object(SimpleXMLElement)#%d (1) { + [0]=> + string(5) "first" +} +===sxe->elem1[0]->attr1 +bool(false) +bool(false) +int(0) +object(SimpleXMLElement)#%d (0) { +} +===sxe->elem1[1] +bool(true) +bool(true) +int(0) +object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(2) { + ["attr1"]=> + string(2) "11" + ["attr2"]=> + string(2) "12" + } +} +===sxe->elem1[2] +bool(false) +bool(false) +int(0) +NULL +===sxe->elem11 +bool(true) +bool(true) +int(1) +object(SimpleXMLElement)#%d (1) { + ["elem111"]=> + object(SimpleXMLElement)#%d (1) { + ["elem1111"]=> + object(SimpleXMLElement)#%d (0) { + } + } +} +===sxe->elem11->elem111 +bool(true) +bool(true) +int(1) +object(SimpleXMLElement)#%d (1) { + ["elem1111"]=> + object(SimpleXMLElement)#%d (0) { + } +} +===sxe->elem11->elem111->elem1111 +bool(true) +bool(true) +int(1) +object(SimpleXMLElement)#%d (0) { +} +===sxe->elem22 +bool(false) +bool(false) +int(0) +object(SimpleXMLElement)#%d (0) { +} +===sxe->elem22->elem222 +bool(false) +bool(false) +int(0) +NULL +===sxe->elem22->attr22 +bool(false) +bool(false) +int(0) +NULL +===sxe->elem22["attr22"] +bool(false) +bool(false) +int(0) +NULL +===DONE=== diff --git a/ext/simplexml/tests/000.xml b/ext/simplexml/tests/000.xml new file mode 100755 index 0000000000..b0f2785463 --- /dev/null +++ b/ext/simplexml/tests/000.xml @@ -0,0 +1,16 @@ + + +%incent; +]> + + There is some text. + + + + + + Here is some more + + + \ No newline at end of file diff --git a/ext/simplexml/tests/001.phpt b/ext/simplexml/tests/001.phpt index cacc2d3066..0be77710e5 100644 --- a/ext/simplexml/tests/001.phpt +++ b/ext/simplexml/tests/001.phpt @@ -5,39 +5,39 @@ SimpleXML: Simple document --FILE-- ---EXPECT-- -SimpleXMLElement Object -( - [elem1] => SimpleXMLElement Object - ( - [comment] => SimpleXMLElement Object - ( - ) - - [elem2] => SimpleXMLElement Object - ( - [elem3] => SimpleXMLElement Object - ( - [elem4] => SimpleXMLElement Object - ( - [test] => SimpleXMLElement Object - ( - ) - - ) - - ) - - ) - - ) - -) ----Done--- +===DONE=== +--EXPECTF-- +object(SimpleXMLElement)#%d (2) { + ["@attributes"]=> + array(1) { + ["id"]=> + string(5) "elem1" + } + ["elem1"]=> + object(SimpleXMLElement)#%d (3) { + ["@attributes"]=> + array(1) { + ["attr1"]=> + string(5) "first" + } + ["comment"]=> + object(SimpleXMLElement)#%d (0) { + } + ["elem2"]=> + object(SimpleXMLElement)#%d (1) { + ["elem3"]=> + object(SimpleXMLElement)#%d (1) { + ["elem4"]=> + object(SimpleXMLElement)#%d (1) { + ["test"]=> + object(SimpleXMLElement)#%d (0) { + } + } + } + } + } +} +===DONE=== diff --git a/ext/simplexml/tests/002.phpt b/ext/simplexml/tests/002.phpt index 95d644fe71..4f1f6b6224 100644 --- a/ext/simplexml/tests/002.phpt +++ b/ext/simplexml/tests/002.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and clone +SimpleXML: clone --SKIPIF-- --FILE-- @@ -26,37 +26,39 @@ $sxe = simplexml_load_string($xml); $copy = clone $sxe; -print_r($copy); - -echo "---Done---\n"; +var_dump($copy); ?> ---EXPECT-- -SimpleXMLElement Object -( - [elem1] => SimpleXMLElement Object - ( - [comment] => SimpleXMLElement Object - ( - ) - - [elem2] => SimpleXMLElement Object - ( - [elem3] => SimpleXMLElement Object - ( - [elem4] => SimpleXMLElement Object - ( - [test] => SimpleXMLElement Object - ( - ) - - ) - - ) - - ) - - ) - -) ----Done--- +===DONE=== +--EXPECTF-- +object(SimpleXMLElement)#%d (2) { + ["@attributes"]=> + array(1) { + ["id"]=> + string(5) "elem1" + } + ["elem1"]=> + object(SimpleXMLElement)#%d (3) { + ["@attributes"]=> + array(1) { + ["attr1"]=> + string(5) "first" + } + ["comment"]=> + object(SimpleXMLElement)#%d (0) { + } + ["elem2"]=> + object(SimpleXMLElement)#%d (1) { + ["elem3"]=> + object(SimpleXMLElement)#%d (1) { + ["elem4"]=> + object(SimpleXMLElement)#%d (1) { + ["test"]=> + object(SimpleXMLElement)#%d (0) { + } + } + } + } + } +} +===DONE=== diff --git a/ext/simplexml/tests/003.phpt b/ext/simplexml/tests/003.phpt index 96aad372da..105f616d60 100755 --- a/ext/simplexml/tests/003.phpt +++ b/ext/simplexml/tests/003.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and Entities +SimpleXML: Entities --SKIPIF-- --FILE-- @@ -26,44 +26,44 @@ $xml =<< EOF; -$sxe = simplexml_load_string($xml); - -print_r($sxe); - -echo "---Done---\n"; +var_dump(simplexml_load_string($xml)); ?> ---EXPECT-- -SimpleXMLElement Object -( - [elem1] => SimpleXMLElement Object - ( - [comment] => SimpleXMLElement Object - ( - ) - - [elem2] => SimpleXMLElement Object - ( - [elem3] => SimpleXMLElement Object - ( - [included-entity] => SimpleXMLElement Object - ( - [included-entity] => This is text included from an entity - ) - - [elem4] => SimpleXMLElement Object - ( - [test] => SimpleXMLElement Object - ( - ) - - ) - - ) - - ) - - ) - -) ----Done--- +===DONE=== +--EXPECTF-- +object(SimpleXMLElement)#%d (2) { + ["@attributes"]=> + array(1) { + ["id"]=> + string(5) "elem1" + } + ["elem1"]=> + object(SimpleXMLElement)#%d (3) { + ["@attributes"]=> + array(1) { + ["attr1"]=> + string(5) "first" + } + ["comment"]=> + object(SimpleXMLElement)#%d (0) { + } + ["elem2"]=> + object(SimpleXMLElement)#%d (1) { + ["elem3"]=> + object(SimpleXMLElement)#%d (2) { + ["included-entity"]=> + object(SimpleXMLElement)#%d (1) { + ["included-entity"]=> + string(36) "This is text included from an entity" + } + ["elem4"]=> + object(SimpleXMLElement)#%d (1) { + ["test"]=> + object(SimpleXMLElement)#%d (0) { + } + } + } + } + } +} +===DONE=== diff --git a/ext/simplexml/tests/004.phpt b/ext/simplexml/tests/004.phpt index 392b1d4981..21cb5469e0 100755 --- a/ext/simplexml/tests/004.phpt +++ b/ext/simplexml/tests/004.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and CDATA +SimpleXML: CDATA --SKIPIF-- --FILE-- @@ -25,7 +25,7 @@ $sxe = simplexml_load_string(<<elem1; $elem2 = $elem1->elem2; @@ -33,33 +33,36 @@ var_dump(trim((string)$elem2)); ?> ===DONE=== ---EXPECT-- -SimpleXMLElement Object -( - [elem1] => SimpleXMLElement Object - ( - [comment] => SimpleXMLElement Object - ( - ) - - [elem2] => SimpleXMLElement Object - ( - [elem3] => SimpleXMLElement Object - ( - [elem4] => SimpleXMLElement Object - ( - [test] => SimpleXMLElement Object - ( - ) - - ) - - ) - - ) - - ) - -) +--EXPECTF-- +object(SimpleXMLElement)#%d (2) { + ["@attributes"]=> + array(1) { + ["id"]=> + string(5) "elem1" + } + ["elem1"]=> + object(SimpleXMLElement)#%d (3) { + ["@attributes"]=> + array(1) { + ["attr1"]=> + string(5) "first" + } + ["comment"]=> + object(SimpleXMLElement)#%d (0) { + } + ["elem2"]=> + object(SimpleXMLElement)#%d (1) { + ["elem3"]=> + object(SimpleXMLElement)#%d (1) { + ["elem4"]=> + object(SimpleXMLElement)#%d (1) { + ["test"]=> + object(SimpleXMLElement)#%d (0) { + } + } + } + } + } +} string(11) "CDATA block" ===DONE=== diff --git a/ext/simplexml/tests/005.phpt b/ext/simplexml/tests/005.phpt index 237a5d2616..1411065435 100755 --- a/ext/simplexml/tests/005.phpt +++ b/ext/simplexml/tests/005.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and text data +SimpleXML: Text data --SKIPIF-- --FILE-- diff --git a/ext/simplexml/tests/006.phpt b/ext/simplexml/tests/006.phpt index 9360b2dff3..72ad0c8089 100755 --- a/ext/simplexml/tests/006.phpt +++ b/ext/simplexml/tests/006.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and foreach +SimpleXML: foreach --SKIPIF-- --FILE-- diff --git a/ext/simplexml/tests/007.phpt b/ext/simplexml/tests/007.phpt index b55d324966..51d7a847f7 100755 --- a/ext/simplexml/tests/007.phpt +++ b/ext/simplexml/tests/007.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and attributes +SimpleXML: Attributes --SKIPIF-- --FILE-- @@ -48,7 +48,12 @@ var_dump($a); ===Done=== --EXPECTF-- ===Property=== -object(SimpleXMLElement)#%d (2) { +object(SimpleXMLElement)#%d (3) { + ["@attributes"]=> + array(1) { + ["attr1"]=> + string(5) "first" + } ["comment"]=> object(SimpleXMLElement)#%d (0) { } diff --git a/ext/simplexml/tests/008.phpt b/ext/simplexml/tests/008.phpt index 3554b32040..4fda204a2f 100644 --- a/ext/simplexml/tests/008.phpt +++ b/ext/simplexml/tests/008.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and XPath +SimpleXML: XPath --SKIPIF-- --FILE-- diff --git a/ext/simplexml/tests/009.phpt b/ext/simplexml/tests/009.phpt index 2115dd3142..a76f3d1116 100755 --- a/ext/simplexml/tests/009.phpt +++ b/ext/simplexml/tests/009.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and foreach +SimpleXML: foreach --SKIPIF-- --FILE-- @@ -31,7 +31,7 @@ EOF foreach($sxe->children() as $name=>$val) { var_dump($name); var_dump(get_class($val)); - var_dump(trim((string)$val)); + var_dump(trim($val)); } ?> ===DONE=== diff --git a/ext/simplexml/tests/010.phpt b/ext/simplexml/tests/010.phpt index ea6c7fd079..267780905b 100644 --- a/ext/simplexml/tests/010.phpt +++ b/ext/simplexml/tests/010.phpt @@ -26,38 +26,39 @@ $xml =<< EOF; -$sxe = simplexml_load_string($xml, 'simplexml_inherited'); - -print_r($sxe); +var_dump(simplexml_load_string($xml, 'simplexml_inherited')); ?> ===DONE=== ---EXPECT-- -simplexml_inherited Object -( - [elem1] => simplexml_inherited Object - ( - [comment] => simplexml_inherited Object - ( - ) - - [elem2] => simplexml_inherited Object - ( - [elem3] => simplexml_inherited Object - ( - [elem4] => simplexml_inherited Object - ( - [test] => simplexml_inherited Object - ( - ) - - ) - - ) - - ) - - ) - -) +--EXPECTF-- +object(simplexml_inherited)#%d (2) { + ["@attributes"]=> + array(1) { + ["id"]=> + string(5) "elem1" + } + ["elem1"]=> + object(simplexml_inherited)#%d (3) { + ["@attributes"]=> + array(1) { + ["attr1"]=> + string(5) "first" + } + ["comment"]=> + object(simplexml_inherited)#%d (0) { + } + ["elem2"]=> + object(simplexml_inherited)#%d (1) { + ["elem3"]=> + object(simplexml_inherited)#%d (1) { + ["elem4"]=> + object(simplexml_inherited)#%d (1) { + ["test"]=> + object(simplexml_inherited)#%d (0) { + } + } + } + } + } +} ===DONE=== diff --git a/ext/simplexml/tests/011.phpt b/ext/simplexml/tests/011.phpt index f48c9f1eec..74ea4705ca 100755 --- a/ext/simplexml/tests/011.phpt +++ b/ext/simplexml/tests/011.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and echo/print +SimpleXML: echo/print --SKIPIF-- asXML(); $sxe[] = "error"; +__HALT_COMPILER(); ?> ===DONE=== --EXPECTF-- diff --git a/ext/simplexml/tests/013.phpt b/ext/simplexml/tests/013.phpt index fbd80b0c44..56c57dfbc2 100755 --- a/ext/simplexml/tests/013.phpt +++ b/ext/simplexml/tests/013.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and Split text content +SimpleXML: Split text content --SKIPIF-- string(1) "5" } -===DONE=== \ No newline at end of file +===DONE=== diff --git a/ext/simplexml/tests/014b.phpt b/ext/simplexml/tests/014b.phpt index 14bd6ce864..034396751a 100755 --- a/ext/simplexml/tests/014b.phpt +++ b/ext/simplexml/tests/014b.phpt @@ -52,4 +52,4 @@ object(SimpleXMLElement)#%d (1) { [0]=> string(1) "5" } -===DONE=== \ No newline at end of file +===DONE=== diff --git a/ext/simplexml/tests/019.phpt b/ext/simplexml/tests/019.phpt index a54a1bdd52..aec74ba42e 100755 --- a/ext/simplexml/tests/019.phpt +++ b/ext/simplexml/tests/019.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and foreach with children() +SimpleXML: foreach with children() --SKIPIF-- --FILE-- diff --git a/ext/simplexml/tests/020.phpt b/ext/simplexml/tests/020.phpt index a2a328736c..9e91b5ac3a 100755 --- a/ext/simplexml/tests/020.phpt +++ b/ext/simplexml/tests/020.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML attribute compared to string +SimpleXML: Attribute compared to string --SKIPIF-- --FILE-- diff --git a/ext/simplexml/tests/021.phpt b/ext/simplexml/tests/021.phpt index e58e26d6ee..d5138685f5 100644 --- a/ext/simplexml/tests/021.phpt +++ b/ext/simplexml/tests/021.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML element check +SimpleXML: Element check --SKIPIF-- --FILE-- diff --git a/ext/simplexml/tests/022.phpt b/ext/simplexml/tests/022.phpt index 08cb908c9c..2af4a1dd28 100755 --- a/ext/simplexml/tests/022.phpt +++ b/ext/simplexml/tests/022.phpt @@ -1,5 +1,5 @@ --TEST-- -SimpleXML and attributes inside foreach +SimpleXML: Attributes inside foreach --SKIPIF-- --FILE-- @@ -12,6 +12,13 @@ EOF; $sxe = simplexml_load_string($xml); +echo "===CONTENT===\n"; +var_dump($sxe->content); + +echo "===FILE===\n"; +var_dump($sxe->content->file); + +echo "===FOREACH===\n"; foreach($sxe->content->file as $file) { var_dump($file); @@ -21,7 +28,32 @@ foreach($sxe->content->file as $file) ?> ===DONE=== --EXPECTF-- -object(SimpleXMLElement)#%d (0) { +===CONTENT=== +object(SimpleXMLElement)#%d (1) { + ["file"]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["glob"]=> + string(11) "slide_*.xml" + } + } +} +===FILE=== +object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["glob"]=> + string(11) "slide_*.xml" + } +} +===FOREACH=== +object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["glob"]=> + string(11) "slide_*.xml" + } } object(SimpleXMLElement)#%d (1) { [0]=> diff --git a/ext/simplexml/tests/023.phpt b/ext/simplexml/tests/023.phpt index dd6dde59d7..515a1460c9 100755 --- a/ext/simplexml/tests/023.phpt +++ b/ext/simplexml/tests/023.phpt @@ -22,7 +22,12 @@ var_dump($sxe['attr']); ?> ===DONE=== --EXPECTF-- -object(SimpleXMLElement)#%d (0) { +object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr"]=> + string(%d) "foo%sbar%sbaz" + } } object(SimpleXMLElement)#%d (1) { [0]=> diff --git a/ext/simplexml/tests/024.phpt b/ext/simplexml/tests/024.phpt new file mode 100755 index 0000000000..9f31fd5e93 --- /dev/null +++ b/ext/simplexml/tests/024.phpt @@ -0,0 +1,175 @@ +--TEST-- +SimpleXML: XPath and attributes +--SKIPIF-- + +--FILE-- + + + + + + +EOF; + +$sxe = simplexml_load_string($xml); + +function test($xpath) +{ + global $sxe; + + echo "===$xpath===\n"; + var_dump($sxe->xpath($xpath)); +} + +test('elem/@attr2'); +test('//@attr2'); +test('//@*'); +test('elem[2]/@attr2'); + +?> +===DONE=== +--EXPECTF-- +===elem/@attr2=== +array(3) { + [0]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr2"]=> + string(2) "12" + } + } + [1]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr2"]=> + string(2) "22" + } + } + [2]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr2"]=> + string(2) "32" + } + } +} +===//@attr2=== +array(3) { + [0]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr2"]=> + string(2) "12" + } + } + [1]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr2"]=> + string(2) "22" + } + } + [2]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr2"]=> + string(2) "32" + } + } +} +===//@*=== +array(9) { + [0]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr1"]=> + string(2) "11" + } + } + [1]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr2"]=> + string(2) "12" + } + } + [2]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr3"]=> + string(2) "13" + } + } + [3]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr1"]=> + string(2) "21" + } + } + [4]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr2"]=> + string(2) "22" + } + } + [5]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr3"]=> + string(2) "23" + } + } + [6]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr1"]=> + string(2) "31" + } + } + [7]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr2"]=> + string(2) "32" + } + } + [8]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr3"]=> + string(2) "33" + } + } +} +===elem[2]/@attr2=== +array(1) { + [0]=> + object(SimpleXMLElement)#%d (1) { + ["@attributes"]=> + array(1) { + ["attr2"]=> + string(2) "22" + } + } +} +===DONE=== diff --git a/ext/simplexml/tests/025.phpt b/ext/simplexml/tests/025.phpt new file mode 100755 index 0000000000..b9e3bbb0dc --- /dev/null +++ b/ext/simplexml/tests/025.phpt @@ -0,0 +1,92 @@ +--TEST-- +SimpleXML: getting namespaces +--SKIPIF-- + +--FILE-- + + +bla + +bla + + + +EOF; + +$sxe = simplexml_load_string($xml); + +var_dump($sxe->getNamespaces()); +var_dump($sxe->getNamespaces(true)); +var_dump($sxe->getDocNamespaces()); +var_dump($sxe->getDocNamespaces(true)); + +$xml =<< + +bla + +EOF; + +$sxe = simplexml_load_string($xml); + +var_dump($sxe->getNamespaces()); +var_dump($sxe->getDocNamespaces()); + +$xml =<< + +EOF; + +$sxe = simplexml_load_string($xml); + +var_dump($sxe->getNamespaces()); +var_dump($sxe->getDocNamespaces()); + +?> +===DONE=== + +--EXPECTF-- +array(1) { + ["xhtml"]=> + string(31) "http://www.w3.org/TR/REC-html40" +} +array(3) { + ["xhtml"]=> + string(31) "http://www.w3.org/TR/REC-html40" + ["html"]=> + string(28) "http://www.w3.org/1999/xhtml" + ["foo"]=> + string(6) "foobar" +} +array(2) { + ["html"]=> + string(28) "http://www.w3.org/1999/xhtml" + ["xhtml"]=> + string(31) "http://www.w3.org/TR/REC-html40" +} +array(4) { + ["html"]=> + string(28) "http://www.w3.org/1999/xhtml" + ["xhtml"]=> + string(31) "http://www.w3.org/TR/REC-html40" + ["foo"]=> + string(6) "foobar" + ["baz"]=> + string(9) "foobarbaz" +} +array(1) { + [""]=> + string(28) "http://www.w3.org/1999/xhtml" +} +array(1) { + [""]=> + string(28) "http://www.w3.org/1999/xhtml" +} +array(0) { +} +array(0) { +} +===DONE=== diff --git a/ext/simplexml/tests/bug27010.phpt b/ext/simplexml/tests/bug27010.phpt index 9ba9f7b6bd..9b08932cd9 100755 --- a/ext/simplexml/tests/bug27010.phpt +++ b/ext/simplexml/tests/bug27010.phpt @@ -1,5 +1,5 @@ --TEST-- -#27010: segfault and node text not displayed when returned from children() +Bug #27010 (segfault and node text not displayed when returned from children()) --FILE-- '); -echo $root->children('reserved-ns')->child; -echo "\n"; -echo $root->children('special-ns')->child; -foreach ($root->child as $child) { - echo "$child\n"; -} -echo "\n---Done---\n"; +var_dump($root->children('reserved-ns')->child); +var_dump($root->children('special-ns')->child); +var_dump((string)$root->children('reserved-ns')->child); +var_dump((string)$root->children('special-ns')->child); +var_dump($root->child); ?> ---EXPECT-- -Hello -World ----Done--- +===DONE=== +--EXPECTF-- +object(SimpleXMLElement)#%d (1) { + [0]=> + string(5) "Hello" +} +object(SimpleXMLElement)#%d (1) { + [0]=> + string(5) "World" +} +string(5) "Hello" +string(5) "World" +object(SimpleXMLElement)#%d (0) { +} +===DONE=== diff --git a/ext/simplexml/tests/simplexml_import_dom.phpt b/ext/simplexml/tests/simplexml_import_dom.phpt index c66ba8f087..76e7f041dd 100755 --- a/ext/simplexml/tests/simplexml_import_dom.phpt +++ b/ext/simplexml/tests/simplexml_import_dom.phpt @@ -1,5 +1,5 @@ --TEST-- -Interop: simplexml_import_dom +SimpleXML [interop]: simplexml_import_dom --SKIPIF-- -- 2.50.1