diff options
| author | Marcus Boerger <helly@php.net> | 2003-11-23 16:20:58 +0000 | 
|---|---|---|
| committer | Marcus Boerger <helly@php.net> | 2003-11-23 16:20:58 +0000 | 
| commit | fc117add30f5d3808bb9afbe219204d16e586ea0 (patch) | |
| tree | 7a0f79ccecf98ce3436ec74567c350dbe6a9ce0e | |
| parent | ceaddf238b4cddc0e8201838141bb2876dc7ab76 (diff) | |
| download | php-git-fc117add30f5d3808bb9afbe219204d16e586ea0.tar.gz | |
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
| -rw-r--r-- | ext/simplexml/php_simplexml.h | 6 | ||||
| -rw-r--r-- | ext/simplexml/simplexml.c | 323 | ||||
| -rwxr-xr-x | ext/simplexml/tests/006.phpt | 21 | ||||
| -rwxr-xr-x | ext/simplexml/tests/006.xml | 3 | 
4 files changed, 235 insertions, 118 deletions
diff --git a/ext/simplexml/php_simplexml.h b/ext/simplexml/php_simplexml.h index 1b325ca9cd..146a818578 100644 --- a/ext/simplexml/php_simplexml.h +++ b/ext/simplexml/php_simplexml.h @@ -64,6 +64,12 @@ typedef struct {  	HashTable *properties;  	simplexml_nsmap *nsmapptr;  	xmlXPathContextPtr xpath; +	struct { +		xmlNodePtr            node; +		char                  *name; +		int                   namelen; +		zval                  *data; +	} iter;  } php_sxe_object; diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 9012134019..acd138303c 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -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 @@ php_sxe_fetch_object(zval *object TSRMLS_DC)  /* {{{ _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 @@ match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *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) +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 @@ next_iter:  /* {{{ 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_property_read(zval *object, zval *member, zend_bool silent TSRMLS_DC)  /* {{{ 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 @@ sxe_method_get(zval *object, char *name, int len TSRMLS_DC)  }  /* }}} */ -/* {{{ 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 @@ simplexml_ce_xpath_search(INTERNAL_FUNCTION_PARAMETERS)  			_node_as_zval(sxe, result->nodeTab[i], value TSRMLS_CC);  		}  		add_next_index_zval(return_value, value); -	} -	 +	}	  }  /* }}} */ @@ -775,12 +779,26 @@ simplexml_ce_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type)  }  /* }}} */ +/* {{{ 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_register_ns(INTERNAL_FUNCTION_PARAMETERS)  /* {{{ 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_string(INTERNAL_FUNCTION_PARAMETERS)  /* {{{ 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 @@ simplexml_ce_to_xml_file(INTERNAL_FUNCTION_PARAMETERS)  }  /* }}} */ -/* {{{ 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 @@ static zend_object_handlers sxe_object_handlers = {  	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 @@ _free_ns_entry(void *p, xmlChar *data)  /* {{{ 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 @@ sxe_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)  	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 @@ sxe_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)  		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 @@ PHP_FUNCTION(simplexml_load_string)  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 int php_sxe_iterator_has_more(zend_object_iterator *iter TSRMLS_DC);  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 @@ zend_object_iterator_funcs php_sxe_iterator_funcs = {  	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 @@ static void php_sxe_iterator_current(php_sxe_iterator *iterator TSRMLS_DC)  			}  		} 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 @@ zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object TS  	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 @@ static void php_sxe_iterator_dtor(zend_object_iterator *iter TSRMLS_DC)  	zval_ptr_dtor((zval**)&iterator->intern.data); -	if (iterator->data) { -		zval_ptr_dtor(&iterator->data); -	}  	efree(iterator);  } @@ -1276,37 +1232,147 @@ static int php_sxe_iterator_has_more(zend_object_iterator *iter TSRMLS_DC)  {  	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 @@ zend_module_entry simplexml_module_entry = {  #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(); diff --git a/ext/simplexml/tests/006.phpt b/ext/simplexml/tests/006.phpt index ac7c77e91c..d17f0429c2 100755 --- a/ext/simplexml/tests/006.phpt +++ b/ext/simplexml/tests/006.phpt @@ -12,30 +12,45 @@ foreach($sxe as $name => $data) {  	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=== diff --git a/ext/simplexml/tests/006.xml b/ext/simplexml/tests/006.xml index d8d93debde..d518d85e1e 100755 --- a/ext/simplexml/tests/006.xml +++ b/ext/simplexml/tests/006.xml @@ -20,5 +20,8 @@   </elem1>   <elem11 attr2='second'>    Bla bla 2. +  <elem111> +   Foo Bar +  </elem111>   </elem11>  </sxe> 
\ No newline at end of file  | 
