]> granicus.if.org Git - php/commitdiff
- MFH
authorMarcus Boerger <helly@php.net>
Tue, 29 Nov 2005 02:51:07 +0000 (02:51 +0000)
committerMarcus Boerger <helly@php.net>
Tue, 29 Nov 2005 02:51:07 +0000 (02:51 +0000)
  . 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.

28 files changed:
ext/simplexml/simplexml.c
ext/simplexml/tests/000.phpt [new file with mode: 0755]
ext/simplexml/tests/000.xml [new file with mode: 0755]
ext/simplexml/tests/001.phpt
ext/simplexml/tests/002.phpt
ext/simplexml/tests/003.phpt
ext/simplexml/tests/004.phpt
ext/simplexml/tests/005.phpt
ext/simplexml/tests/006.phpt
ext/simplexml/tests/007.phpt
ext/simplexml/tests/008.phpt
ext/simplexml/tests/009.phpt
ext/simplexml/tests/010.phpt
ext/simplexml/tests/011.phpt
ext/simplexml/tests/012.phpt
ext/simplexml/tests/013.phpt
ext/simplexml/tests/014a.phpt
ext/simplexml/tests/014b.phpt
ext/simplexml/tests/019.phpt
ext/simplexml/tests/020.phpt
ext/simplexml/tests/021.phpt
ext/simplexml/tests/022.phpt
ext/simplexml/tests/023.phpt
ext/simplexml/tests/024.phpt [new file with mode: 0755]
ext/simplexml/tests/025.phpt [new file with mode: 0755]
ext/simplexml/tests/bug27010.phpt
ext/simplexml/tests/profile11.phpt
ext/simplexml/tests/simplexml_import_dom.phpt

index 985343bbce99c95f3a7b6144b13dad2f3253dba8..310f3718d3c978f5f50e0b7c001bdfffd95e92f4 100644 (file)
@@ -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 (executable)
index 0000000..51dbe3b
--- /dev/null
@@ -0,0 +1,254 @@
+--TEST--
+SimpleXML: var_dump()
+--SKIPIF--
+<?php if (!extension_loaded("simplexml")) print "skip"; ?>
+--FILE--
+<?php 
+
+$sxe = simplexml_load_file(dirname(__FILE__).'/000.xml');
+
+function test($what)
+{
+       global $sxe;
+       echo "===$what\n";
+       eval("var_dump(isset(\$$what));");
+       eval("var_dump((bool)\$$what);");
+       eval("var_dump(count(\$$what));");
+       eval("var_dump(\$$what);");
+}
+
+test('sxe');
+test('sxe->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===
+<?php exit(0); ?>
+--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 (executable)
index 0000000..b0f2785
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version='1.0'?>
+<!DOCTYPE sxe SYSTEM "sxe.dtd" [
+<!ENTITY % incent SYSTEM "sxe.ent">
+%incent;
+]>
+<sxe id="123">
+ <elem1 attr1='first' attr2='second'>There is some text.<!-- comment --><elem2 att25='25' att42='42'>
+   <elem3>
+    <elem4>
+     <?test processing instruction ?>
+    </elem4>
+   </elem3>
+  </elem2>Here is some more</elem1>
+ <elem1 attr1='11' attr2='12'/>
+ <elem11><elem111><elem1111/></elem111></elem11>
+</sxe>
\ No newline at end of file
index cacc2d30663793924e70d9c223917fbdf3102644..0be77710e5fbb3a9c3ba097c69e194cb5f697bd9 100644 (file)
@@ -5,39 +5,39 @@ SimpleXML: Simple document
 --FILE--
 <?php 
 
-$sxe = simplexml_load_file(dirname(__FILE__).'/sxe.xml');
-
-print_r($sxe);
-
-echo "---Done---\n";
+var_dump(simplexml_load_file(dirname(__FILE__).'/sxe.xml'));
 
 ?>
---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===
index 95d644fe7142371950b72094209cb261c9b0e6f6..4f1f6b622406ce45c1ce55445d5558add7f88788 100644 (file)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and clone
+SimpleXML: clone
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 --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===
index 96aad372dac0d9e51701d2fa5b1dbee9e008464f..105f616d60e52300d872c0dd1ed61b112d31f654 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and Entities
+SimpleXML: Entities
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 --FILE--
@@ -26,44 +26,44 @@ $xml =<<<EOF
 </sxe>
 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===
index 392b1d4981ec38ecfd85955226537e2aab20a3af..21cb5469e01066c013ccb06f9c9e4199881dd1cb 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and CDATA
+SimpleXML: CDATA
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 --FILE--
@@ -25,7 +25,7 @@ $sxe = simplexml_load_string(<<<EOF
 EOF
 );
 
-print_r($sxe);
+var_dump($sxe);
 
 $elem1 = $sxe->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===
index 237a5d26169d13ce714001d88a5b06374671c0c5..14110654351463856c63560baee3655cda1ea043 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and text data
+SimpleXML: Text data
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 --FILE--
index 9360b2dff314d2ff1d19bbc912685a7843142c68..72ad0c80893d2e06097ef432cfaf26bd78a7a7b9 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and foreach
+SimpleXML: foreach
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 --FILE--
index b55d324966dbb361a04717aa497b0f6cf4de8689..51d7a847f7e58031b1ec3dfde692c64fd704bd04 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and attributes
+SimpleXML: Attributes
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 --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) {
   }
index 3554b32040463123b2c19e6b57c1f9c651855f3f..4fda204a2fe3030a176c80fa491354785e26eba4 100644 (file)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and XPath 
+SimpleXML: XPath 
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 --FILE--
index 2115dd31424f9ef93994d64db7466fdb5a4ac390..a76f3d1116172aee5e1f133024d547feb84d5766 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and foreach 
+SimpleXML: foreach 
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 --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===
index ea6c7fd079194d2c53f21ecfbe65ef0184a92f8d..267780905b8c89e32250cf24a0edf25c11ef8a25 100644 (file)
@@ -26,38 +26,39 @@ $xml =<<<EOF
 </sxe>
 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===
index f48c9f1eecaa0fca435ce8bafbcf05a5b534c779..74ea4705cad0838ac6243b314d8024dde1e9503e 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and echo/print
+SimpleXML: echo/print
 --SKIPIF--
 <?php 
        if (!extension_loaded('simplexml')) print 'skip';
index 79c01107fe8768d1b7595af5f41f2b49e6104583..2fc9bec41e2b832b51f7b8d019690e745976312c 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and Attribute creation
+SimpleXML: Attribute creation
 --SKIPIF--
 <?php 
        if (!extension_loaded('simplexml')) print 'skip';
@@ -26,6 +26,7 @@ echo $sxe->asXML();
 
 $sxe[] = "error";
 
+__HALT_COMPILER();
 ?>
 ===DONE===
 --EXPECTF--
index fbd80b0c446ef9149b60314e11a23151ad86f599..56c57dfbc2f59914189231e4eea8147366696c8e 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and Split text content
+SimpleXML: Split text content
 --SKIPIF--
 <?php 
        if (!extension_loaded('simplexml')) print 'skip';
index 770cb448126c0cddaf1a0c3a5901a055fe167e64..649828b4ddf595c5cc35cb8e88fd18a779d24f18 100755 (executable)
@@ -53,4 +53,4 @@ object(SimpleXMLElement)#%d (1) {
   [0]=>
   string(1) "5"
 }
-===DONE===
\ No newline at end of file
+===DONE===
index 14bd6ce864a867b001c3eeb929cdd307357115c3..034396751a2596fb0be126779129fcfa1823c3fd 100755 (executable)
@@ -52,4 +52,4 @@ object(SimpleXMLElement)#%d (1) {
   [0]=>
   string(1) "5"
 }
-===DONE===
\ No newline at end of file
+===DONE===
index a54a1bdd52e9250792567d5ef083a180a471590c..aec74ba42e71a46176072d5d55892856a44c86f5 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and foreach with children()
+SimpleXML: foreach with children()
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 --FILE--
index a2a328736cc9c60ac69ac6c3cf25af8ff400437a..9e91b5ac3a976cff8250c87b57fe94cf4d9450a7 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML attribute compared to string
+SimpleXML: Attribute compared to string
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?> 
 --FILE--
index e58e26d6ee20c311babd4a8167acc1ce315e4173..d5138685f5e12da0a400d66ea19a3cbec3b9c278 100644 (file)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML element check
+SimpleXML: Element check
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?> 
 --FILE--
index 08cb908c9c0aa2d07b5f47dc6ebd8c412db89538..2af4a1dd280fd7b9fa57640fedeb59b2cc1ee9e8 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-SimpleXML and attributes inside foreach
+SimpleXML: Attributes inside foreach
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 --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]=>
index dd6dde59d78a57368e93956056ebcac01a71e87d..515a1460c9d4f41a67a4e8b0b526c3958cceac5a 100755 (executable)
@@ -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 (executable)
index 0000000..9f31fd5
--- /dev/null
@@ -0,0 +1,175 @@
+--TEST--
+SimpleXML: XPath and attributes
+--SKIPIF--
+<?php if (!extension_loaded("simplexml")) print "skip"; ?>
+--FILE--
+<?php
+
+$xml =<<<EOF
+<?xml version='1.0'?>
+<root>
+<elem attr1='11' attr2='12' attr3='13'/>
+<elem attr1='21' attr2='22' attr3='23'/>
+<elem attr1='31' attr2='32' attr3='33'/>
+</root>
+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 (executable)
index 0000000..b9e3bbb
--- /dev/null
@@ -0,0 +1,92 @@
+--TEST--
+SimpleXML: getting namespaces
+--SKIPIF--
+<?php if (!extension_loaded("simplexml")) print "skip"; ?>
+--FILE--
+<?php
+
+$xml =<<<EOF
+<?xml version='1.0'?>
+<xhtml:html xmlns:html='http://www.w3.org/1999/xhtml' xmlns:xhtml='http://www.w3.org/TR/REC-html40'>
+<xhtml:head><xhtml:title xmlns:xhtml='http://www.w3.org/TR/REC-html401'>bla</xhtml:title></xhtml:head>
+<xhtml:body html:title="b">
+<html:h1>bla</html:h1>
+<foo:bar xmlns:foo='foobar' xmlns:baz='foobarbaz'/>
+</xhtml:body>
+</xhtml:html>
+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 =<<<EOF
+<?xml version='1.0'?>
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head><title xmlns='http://www.w3.org/TR/REC-html40'>bla</title></head>
+</html>
+EOF;
+
+$sxe = simplexml_load_string($xml);
+
+var_dump($sxe->getNamespaces());
+var_dump($sxe->getDocNamespaces());
+
+$xml =<<<EOF
+<?xml version='1.0'?>
+<root/>
+EOF;
+
+$sxe = simplexml_load_string($xml);
+
+var_dump($sxe->getNamespaces());
+var_dump($sxe->getDocNamespaces());
+
+?>
+===DONE===
+<?php exit(0); ?>
+--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===
index 9ba9f7b6bd38984783521057832d7dab03370d1c..9b08932cd9c0c04cfbf5f5383ef78071eda1e664 100755 (executable)
@@ -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--
 <?php
 
index e68e6bd510ef90e5d421fd2bbe5dc09db28a057a..54c31bf7101e113dbf7d2f805e6cffdc92247e84 100644 (file)
@@ -12,15 +12,24 @@ $root = simplexml_load_string('<?xml version="1.0"?>
 </root>
 ');
 
-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=== 
index c66ba8f087b649af9970ac2cc0753c4f9d86b135..76e7f041dd5a1ac2ca723aaa5ecd085670d3dc4e 100755 (executable)
@@ -1,5 +1,5 @@
 --TEST--
-Interop: simplexml_import_dom
+SimpleXML [interop]: simplexml_import_dom
 --SKIPIF--
 <?php if (!extension_loaded("simplexml")) print "skip"; ?>
 <?php if (!extension_loaded("dom")) print "skip. dom extension not loaded"; ?>