helly Sun Nov 23 11:20:59 2003 EDT Modified files: /php-src/ext/simplexml php_simplexml.h simplexml.c /php-src/ext/simplexml/tests 006.phpt 006.xml Log: Several improvements to the simplexml_element object: - Allow to use it as an instance of Iterator - Prepareto use it as a normal object, including spcialization
Index: php-src/ext/simplexml/php_simplexml.h diff -u php-src/ext/simplexml/php_simplexml.h:1.8 php-src/ext/simplexml/php_simplexml.h:1.9 --- php-src/ext/simplexml/php_simplexml.h:1.8 Sun Oct 26 11:00:58 2003 +++ php-src/ext/simplexml/php_simplexml.h Sun Nov 23 11:20:57 2003 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_simplexml.h,v 1.8 2003/10/26 16:00:58 rrichards Exp $ */ +/* $Id: php_simplexml.h,v 1.9 2003/11/23 16:20:57 helly Exp $ */ #ifndef PHP_SIMPLEXML_H #define PHP_SIMPLEXML_H @@ -64,6 +64,12 @@ HashTable *properties; simplexml_nsmap *nsmapptr; xmlXPathContextPtr xpath; + struct { + xmlNodePtr node; + char *name; + int namelen; + zval *data; + } iter; } php_sxe_object; Index: php-src/ext/simplexml/simplexml.c diff -u php-src/ext/simplexml/simplexml.c:1.85 php-src/ext/simplexml/simplexml.c:1.86 --- php-src/ext/simplexml/simplexml.c:1.85 Fri Nov 14 02:41:05 2003 +++ php-src/ext/simplexml/simplexml.c Sun Nov 23 11:20:57 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: simplexml.c,v 1.85 2003/11/14 07:41:05 helly Exp $ */ +/* $Id: simplexml.c,v 1.86 2003/11/23 16:20:57 helly Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -30,8 +30,17 @@ #include "ext/standard/info.h" #include "php_simplexml.h" +#if HAVE_SPL +#include "ext/spl/spl_iterators.h" +#endif + + zend_class_entry *sxe_class_entry; +#define SXE_ME(func, arg_info, flags) PHP_ME(simplexml_element, func, arg_info, flags) + +#define SXE_METHOD(func) PHP_METHOD(simplexml_element, func) + #define SKIP_TEXT(__p) \ if ((__p)->type == XML_TEXT_NODE) { \ goto next_iter; \ @@ -51,8 +60,7 @@ /* {{{ _node_as_zval() */ -static void -_node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value TSRMLS_DC) +static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value TSRMLS_DC) { php_sxe_object *subnode; @@ -118,8 +126,7 @@ /* {{{ 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) +static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements, zend_bool attribs, zend_bool silent TSRMLS_DC) { zval *return_value; zval *value = NULL; @@ -224,8 +231,7 @@ /* {{{ sxe_property_read() */ -static zval * -sxe_property_read(zval *object, zval *member, zend_bool silent TSRMLS_DC) +static zval * sxe_property_read(zval *object, zval *member, zend_bool silent TSRMLS_DC) { return sxe_prop_dim_read(object, member, 1, 0, silent TSRMLS_CC); } @@ -233,7 +239,7 @@ /* {{{ sxe_dimension_read() */ -static zval *sxe_dimension_read(zval *object, zval *offset TSRMLS_DC) +static zval * sxe_dimension_read(zval *object, zval *offset TSRMLS_DC) { return sxe_prop_dim_read(object, offset, 0, 1, 0 TSRMLS_CC); } @@ -641,10 +647,9 @@ } /* }}} */ -/* {{{ simplexml_ce_xpath_search() - */ -static void -simplexml_ce_xpath_search(INTERNAL_FUNCTION_PARAMETERS) +/* {{{ xsearch() + */ +SXE_METHOD(xsearch) { php_sxe_object *sxe; zval *value; @@ -694,8 +699,7 @@ _node_as_zval(sxe, result->nodeTab[i], value TSRMLS_CC); } add_next_index_zval(return_value, value); - } - + } } /* }}} */ @@ -775,12 +779,26 @@ } /* }}} */ +/* {{{ validate_schema_file + */ +SXE_METHOD(validate_schema_file) +{ + simplexml_ce_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, SCHEMA_FILE); +} +/* }}} */ + +/* {{{ validate_schema_buffer + */ +SXE_METHOD(validate_schema_buffer) +{ + simplexml_ce_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, SCHEMA_BLOB); +} +/* }}} */ #endif /* {{{ simplexml_ce_register_ns() */ -static void -simplexml_ce_register_ns(INTERNAL_FUNCTION_PARAMETERS) +SXE_METHOD(register_ns) { php_sxe_object *sxe; char *nsname; @@ -800,8 +818,7 @@ /* {{{ simplexml_ce_to_xml_string() */ -static void -simplexml_ce_to_xml_string(INTERNAL_FUNCTION_PARAMETERS) +SXE_METHOD(to_xml_string) { php_sxe_object *sxe; xmlChar *strval; @@ -822,8 +839,7 @@ /* {{{ simplexml_ce_to_xml_file() */ -static void -simplexml_ce_to_xml_file(INTERNAL_FUNCTION_PARAMETERS) +SXE_METHOD(to_xml_file) { php_sxe_object *sxe; char *filename; @@ -841,54 +857,6 @@ } /* }}} */ -/* {{{ sxe_call_method() - */ -static int -sxe_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) -{ - if (!strcmp(method, "xsearch")) { - simplexml_ce_xpath_search(INTERNAL_FUNCTION_PARAM_PASSTHRU); -#ifdef LIBXML_SCHEMAS_ENABLED - } else if (!strcmp(method, "validate_schema_file")) { - simplexml_ce_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, SCHEMA_FILE); - } else if (!strcmp(method, "validate_schema_buffer")) { - simplexml_ce_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, SCHEMA_BLOB); -#endif - } else if (!strcmp(method, "register_ns")) { - simplexml_ce_register_ns(INTERNAL_FUNCTION_PARAM_PASSTHRU); - } else if (!strcmp(method, "to_xml")) { - simplexml_ce_to_xml_string(INTERNAL_FUNCTION_PARAM_PASSTHRU); - } else if (!strcmp(method, "to_xml_file")) { - simplexml_ce_to_xml_file(INTERNAL_FUNCTION_PARAM_PASSTHRU); - } else { - return 0; - } - - return 1; -} -/* }}} */ - -/* {{{ sxe_class_entry_get() - */ -static zend_class_entry * -sxe_class_entry_get(zval *object TSRMLS_DC) -{ - return sxe_class_entry; -} -/* }}} */ - -/* {{{ sxe_class_name_get() - */ -static int -sxe_class_name_get(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) -{ - *class_name = estrdup("simplexml_element"); - *class_name_len = sizeof("simplexml_element")-1; - - return 0; -} -/* }}} */ - /* {{{ cast_object() */ static int @@ -1001,10 +969,10 @@ sxe_dimension_delete, sxe_properties_get, sxe_method_get, - sxe_call_method, + NULL, /* zend_get_std_object_handlers()->get_method,*/ sxe_constructor_get, - sxe_class_entry_get, - sxe_class_name_get, + NULL, /* zend_get_std_object_handlers()->get_class_entry,*/ + NULL, /* zend_get_std_object_handlers()->get_class_name,*/ sxe_objects_compare, sxe_object_cast }; @@ -1049,8 +1017,7 @@ /* {{{ sxe_object_dtor() */ -static void -sxe_object_dtor(void *object, zend_object_handle handle TSRMLS_DC) +static void sxe_object_dtor(void *object, zend_object_handle handle TSRMLS_DC) { php_sxe_object *sxe; @@ -1059,6 +1026,10 @@ zend_hash_destroy(sxe->zo.properties); FREE_HASHTABLE(sxe->zo.properties); + if (sxe->iter.data) { + zval_ptr_dtor(&sxe->iter.data); + } + php_libxml_node_decrement_resource((php_libxml_node_object *)sxe TSRMLS_CC); if (--sxe->nsmapptr->refcount == 0) { @@ -1074,27 +1045,19 @@ zend_hash_destroy(sxe->properties); FREE_HASHTABLE(sxe->properties); } - + efree(object); } /* }}} */ /* {{{ php_sxe_object_new() */ -static php_sxe_object * -php_sxe_object_new(TSRMLS_D) +static php_sxe_object* php_sxe_object_new(TSRMLS_D) { php_sxe_object *intern; intern = ecalloc(1, sizeof(php_sxe_object)); intern->zo.ce = sxe_class_entry; - intern->zo.in_get = 0; - intern->zo.in_set = 0; - intern->node = NULL; - intern->document = NULL; - intern->nsmapptr = NULL; - intern->xpath = NULL; - intern->properties = NULL; ALLOC_HASHTABLE(intern->zo.properties); zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0); @@ -1192,10 +1155,6 @@ typedef struct { zend_object_iterator intern; php_sxe_object *sxe; - xmlNodePtr node; - char *name; - int namelen; - zval *data; } php_sxe_iterator; static void php_sxe_iterator_dtor(zend_object_iterator *iter TSRMLS_DC); @@ -1203,6 +1162,7 @@ static void php_sxe_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC); static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC); static void php_sxe_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC); +static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC); zend_object_iterator_funcs php_sxe_iterator_funcs = { php_sxe_iterator_dtor, @@ -1210,15 +1170,19 @@ php_sxe_iterator_current_data, php_sxe_iterator_current_key, php_sxe_iterator_move_forward, - NULL + php_sxe_iterator_rewind, }; -static void php_sxe_iterator_current(php_sxe_iterator *iterator TSRMLS_DC) +static void php_sxe_iterator_current(php_sxe_object *sxe TSRMLS_DC) { xmlNodePtr node; - while (iterator->node) { - node = iterator->node; + if (sxe->iter.data) { + zval_ptr_dtor(&sxe->iter.data); + } + ALLOC_INIT_ZVAL(sxe->iter.data); + while (sxe->iter.node) { + node = sxe->iter.node; SKIP_TEXT(node); @@ -1230,17 +1194,16 @@ } } while (0); - if (!iterator->node->name) { + if (!sxe->iter.node->name) { goto next_iter; } else { - iterator->namelen = xmlStrlen(node->name)+1; - iterator->name = (char *) node->name; - MAKE_STD_ZVAL(iterator->data); - _node_as_zval(iterator->sxe, node, iterator->data TSRMLS_CC); + sxe->iter.namelen = xmlStrlen(node->name)+1; + sxe->iter.name = (char *) node->name; + _node_as_zval(sxe, node, sxe->iter.data TSRMLS_CC); } break; next_iter: - iterator->node = iterator->node->next; + sxe->iter.node = sxe->iter.node->next; } } @@ -1252,10 +1215,6 @@ iterator->intern.data = (void*)object; iterator->intern.funcs = &php_sxe_iterator_funcs; iterator->sxe = php_sxe_fetch_object(object TSRMLS_CC); - GET_NODE(iterator->sxe, iterator->node); - iterator->node = iterator->node->children; - iterator->data = NULL; - php_sxe_iterator_current(iterator TSRMLS_CC); return (zend_object_iterator*)iterator; } @@ -1266,9 +1225,6 @@ zval_ptr_dtor((zval**)&iterator->intern.data); - if (iterator->data) { - zval_ptr_dtor(&iterator->data); - } efree(iterator); } @@ -1276,37 +1232,147 @@ { php_sxe_iterator *iterator = (php_sxe_iterator *)iter; - return iterator->node ? SUCCESS : FAILURE; + return iterator->sxe->iter.node ? SUCCESS : FAILURE; } static void php_sxe_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) { php_sxe_iterator *iterator = (php_sxe_iterator *)iter; - - *data = &iterator->data; + + *data = &iterator->sxe->iter.data; } static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) { php_sxe_iterator *iterator = (php_sxe_iterator *)iter; - *str_key = estrndup(iterator->name, iterator->namelen-1); - *str_key_len = iterator->namelen; + *str_key = estrndup(iterator->sxe->iter.name, iterator->sxe->iter.namelen-1); + *str_key_len = iterator->sxe->iter.namelen; return HASH_KEY_IS_STRING; } static void php_sxe_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC) { php_sxe_iterator *iterator = (php_sxe_iterator *)iter; + + if (iterator->sxe->iter.node) { + iterator->sxe->iter.node = iterator->sxe->iter.node->next; + } + php_sxe_iterator_current(iterator->sxe TSRMLS_CC); +} + +static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC) +{ + php_sxe_iterator *iterator = (php_sxe_iterator *)iter; - if (iterator->data) { - zval_ptr_dtor(&iterator->data); - iterator->data = NULL; + GET_NODE(iterator->sxe, iterator->sxe->iter.node); + if (iterator->sxe->iter.node) { + iterator->sxe->iter.node = iterator->sxe->iter.node->children; } - iterator->node = iterator->node->next; - php_sxe_iterator_current(iterator TSRMLS_CC); + php_sxe_iterator_current(iterator->sxe TSRMLS_CC); } +/* {{{ rewind() + */ +SXE_METHOD(rewind) +{ + php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + + GET_NODE(sxe, sxe->iter.node); + if (sxe->iter.node) { + sxe->iter.node = sxe->iter.node->children; + } + php_sxe_iterator_current(sxe TSRMLS_CC); +} +/* }}} */ + +/* {{{ hasMore() + */ +SXE_METHOD(hasMore) +{ + php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + + RETURN_BOOL(sxe->iter.node); +} +/* }}} */ + +/* {{{ curent() + */ +SXE_METHOD(current) +{ + php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + + REPLACE_ZVAL_VALUE(&return_value, sxe->iter.data, 1); +} +/* }}} */ + +/* {{{ key() + */ +SXE_METHOD(key) +{ + php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + + RETURN_STRINGL(sxe->iter.name, sxe->iter.namelen-1, 1); +} +/* }}} */ + +/* {{{ next() + */ +SXE_METHOD(next) +{ + php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + + if (sxe->iter.node) { + sxe->iter.node = sxe->iter.node->next; + } + php_sxe_iterator_current(sxe TSRMLS_CC); +} +/* }}} */ + +/* {{{ hasChildren() + */ +SXE_METHOD(hasChildren) +{ + php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + php_sxe_object *child = php_sxe_fetch_object(sxe->iter.data TSRMLS_CC); + xmlNodePtr node; + + GET_NODE(child, node); + if (node) { + node = node->children; + } + while (node) { + SKIP_TEXT(node); + + do if (node->ns) { + if (node->parent->ns) { + if (!xmlStrcmp(node->ns->href, node->parent->ns->href)) { + break; + } + } + } while (0); + if (node->type == XML_ELEMENT_NODE) { + break; + } +next_iter: + node = node->next; + } + RETURN_BOOL(node ? 1 : 0); +} +/* }}} */ + +/* {{{ getChildren() + */ +SXE_METHOD(getChildren) +{ + php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + +// REPLACE_ZVAL_VALUE(&return_value, sxe->iter.data, 0); + return_value->type = IS_OBJECT; + return_value->value.obj = zend_objects_store_clone_obj(sxe->iter.data TSRMLS_CC); +} +/* }}} */ + /* {{{ proto simplemxml_element simplexml_import_dom(domNode node) Get a simplexml_element object from dom to allow for processing */ PHP_FUNCTION(simplexml_import_dom) @@ -1379,17 +1445,44 @@ #ifdef COMPILE_DL_SIMPLEXML ZEND_GET_MODULE(simplexml) #endif - + +/* the method table */ +/* each method can have its own parameters and visibility */ +static zend_function_entry sxe_functions[] = { + SXE_ME(register_ns, NULL, ZEND_ACC_PUBLIC) + SXE_ME(to_xml_file, NULL, ZEND_ACC_PUBLIC) + SXE_ME(to_xml_string, NULL, ZEND_ACC_PUBLIC) +#ifdef LIBXML_SCHEMAS_ENABLED + SXE_ME(validate_schema_buffer, NULL, ZEND_ACC_PUBLIC) + SXE_ME(validate_schema_file, NULL, ZEND_ACC_PUBLIC) +#endif + SXE_ME(xsearch, NULL, ZEND_ACC_PUBLIC) + SXE_ME(rewind, NULL, ZEND_ACC_PUBLIC) + SXE_ME(hasMore, NULL, ZEND_ACC_PUBLIC) + SXE_ME(current, NULL, ZEND_ACC_PUBLIC) + SXE_ME(key, NULL, ZEND_ACC_PUBLIC) + SXE_ME(next, NULL, ZEND_ACC_PUBLIC) + SXE_ME(hasChildren, NULL, ZEND_ACC_PUBLIC) + SXE_ME(getChildren, NULL, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + /* {{{ PHP_MINIT_FUNCTION(simplexml) */ PHP_MINIT_FUNCTION(simplexml) { zend_class_entry sxe; - INIT_CLASS_ENTRY(sxe, "simplexml_element", NULL); + INIT_CLASS_ENTRY(sxe, "simplexml_element", sxe_functions); sxe.create_object = sxe_object_new; sxe_class_entry = zend_register_internal_class(&sxe TSRMLS_CC); +#if HAVE_SPL + zend_class_implements(sxe_class_entry TSRMLS_CC, 1, spl_ce_RecursiveIterator); +#endif sxe_class_entry->get_iterator = php_sxe_get_iterator; + sxe_object_handlers.get_method = zend_get_std_object_handlers()->get_method; + sxe_object_handlers.get_class_entry = zend_get_std_object_handlers()->get_class_entry; + sxe_object_handlers.get_class_name = zend_get_std_object_handlers()->get_class_name; php_libxml_initialize(); @@ -1429,7 +1522,7 @@ { php_info_print_table_start(); php_info_print_table_header(2, "Simplexml support", "enabled"); - php_info_print_table_row(2, "Revision", "$Revision: 1.85 $"); + php_info_print_table_row(2, "Revision", "$Revision: 1.86 $"); php_info_print_table_row(2, "Schema support", #ifdef LIBXML_SCHEMAS_ENABLED "enabled"); Index: php-src/ext/simplexml/tests/006.phpt diff -u php-src/ext/simplexml/tests/006.phpt:1.1 php-src/ext/simplexml/tests/006.phpt:1.2 --- php-src/ext/simplexml/tests/006.phpt:1.1 Sun Oct 26 08:18:59 2003 +++ php-src/ext/simplexml/tests/006.phpt Sun Nov 23 11:20:58 2003 @@ -12,30 +12,45 @@ var_dump(trim($data)); } +echo "===CLONE===\n"; + foreach($sxe->__clone() as $name => $data) { var_dump($name); var_dump(trim($data)); } -foreach($sxe->elem1 as $name => $data) { +echo "===ELEMENT===\n"; + +foreach($sxe->elem11 as $name => $data) { var_dump($name); var_dump(trim($data)); } -echo "===Done===\n"; +echo "===COMMENT===\n"; + +foreach($sxe->elem1 as $name => $data) { + var_dump($name); + var_dump(trim($data)); +} ?> +===DONE=== --EXPECT-- string(5) "elem1" string(10) "Bla bla 1." string(6) "elem11" string(10) "Bla bla 2." +===CLONE=== string(5) "elem1" string(10) "Bla bla 1." string(6) "elem11" string(10) "Bla bla 2." +===ELEMENT=== +string(7) "elem111" +string(7) "Foo Bar" +===COMMENT=== string(7) "comment" string(0) "" string(5) "elem2" string(28) "Here we have some text data." -===Done=== +===DONE=== Index: php-src/ext/simplexml/tests/006.xml diff -u php-src/ext/simplexml/tests/006.xml:1.1 php-src/ext/simplexml/tests/006.xml:1.2 --- php-src/ext/simplexml/tests/006.xml:1.1 Sun Oct 26 08:18:59 2003 +++ php-src/ext/simplexml/tests/006.xml Sun Nov 23 11:20:58 2003 @@ -20,5 +20,8 @@ </elem1> <elem11 attr2='second'> Bla bla 2. + <elem111> + Foo Bar + </elem111> </elem11> </sxe> \ No newline at end of file
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php