@@ -1755,22 +1755,58 @@ PHP_METHOD(DOM_Element, getInScopeNamespaces)
17551755	DOM_GET_THIS_OBJ (nodep , id , xmlNodePtr , intern );
17561756
17571757	php_dom_libxml_ns_mapper  * ns_mapper  =  php_dom_get_ns_mapper (intern );
1758- 	php_dom_in_scope_ns  namespaces  =  php_dom_get_in_scope_ns (ns_mapper , nodep , true);
17591758
1760- 	array_init_size (return_value , namespaces .count );
1759+ 	HashTable  prefix_to_ns_table ;
1760+ 	zend_hash_init (& prefix_to_ns_table , 0 , NULL , NULL , false);
1761+ 	zend_hash_real_init_mixed (& prefix_to_ns_table );
1762+ 
1763+ 	/* https://www.w3.org/TR/1999/REC-xpath-19991116/#namespace-nodes */ 
1764+ 	for  (const  xmlNode  * cur  =  nodep ; cur  !=  NULL ; cur  =  cur -> parent ) {
1765+ 		if  (cur -> type  ==  XML_ELEMENT_NODE ) {
1766+ 			for  (const  xmlAttr  * attr  =  cur -> properties ; attr  !=  NULL ; attr  =  attr -> next ) {
1767+ 				if  (attr -> ns  !=  NULL  &&  php_dom_ns_is_fast_ex (attr -> ns , php_dom_ns_is_xmlns_magic_token )
1768+ 					&&  attr -> children  !=  NULL  &&  attr -> children -> content  !=  NULL ) {
1769+ 					const  char  * prefix  =  attr -> ns -> prefix  ==  NULL  ? NULL  : (const  char  * ) attr -> name ;
1770+ 					const  char  * key  =  prefix  ==  NULL  ? ""  : prefix ;
1771+ 					xmlNsPtr  ns  =  php_dom_libxml_ns_mapper_get_ns_raw_strings_nullsafe (ns_mapper , prefix , (const  char  * ) attr -> children -> content );
1772+ 					zend_hash_str_add_ptr (& prefix_to_ns_table , key , strlen (key ), ns );
1773+ 				}
1774+ 			}
1775+ 		}
1776+ 	}
1777+ 
1778+ 	array_init_size (return_value , zend_hash_num_elements (& prefix_to_ns_table ));
1779+ 
1780+ 	xmlNsPtr  ns ;
1781+ 	zend_string  * prefix ;
1782+ 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR (& prefix_to_ns_table , prefix , ns ) {
1783+ 		if  (ZSTR_LEN (prefix ) ==  0  &&  (ns  ==  NULL  ||  ns -> href  ==  NULL  ||  * ns -> href  ==  '\0' )) {
1784+ 			/* Exception: "the value of the xmlns attribute for the nearest such element is non-empty" */ 
1785+ 			continue ;
1786+ 		}
17611787
1762- 	for  (size_t  i  =  0 ; i  <  namespaces .count ; i ++ ) {
1763- 		xmlNsPtr  ns  =  namespaces .list [i ];
1764- 		if  (ns  ==  NULL ) {
1765- 			/* This case corresponds to xmlns="" */ 
1766- 			add_assoc_null (return_value , "" );
1788+ 		zval  zv ;
1789+ 		object_init_ex (& zv , dom_namespace_info_class_entry );
1790+ 		zend_object  * obj  =  Z_OBJ (zv );
1791+ 
1792+ 		if  (ZSTR_LEN (prefix ) !=  0 ) {
1793+ 			ZVAL_STRING (OBJ_PROP_NUM (obj , 0 ), (const  char  * ) ZSTR_VAL (prefix ));
17671794		} else  {
1768- 			const  char  * prefix  =  (const  char  * ) ns -> prefix ;
1769- 			add_assoc_stringl (return_value , prefix  ==  NULL  ? ""  : prefix , (const  char  * ) ns -> href , xmlStrlen (ns -> href ));
1795+ 			ZVAL_NULL (OBJ_PROP_NUM (obj , 0 ));
17701796		}
1771- 	}
17721797
1773- 	php_dom_in_scope_ns_destroy (& namespaces );
1798+ 		if  (ns  !=  NULL  &&  ns -> href  !=  NULL  &&  * ns -> href  !=  '\0' ) {
1799+ 			ZVAL_STRING (OBJ_PROP_NUM (obj , 1 ), (const  char  * ) ns -> href );
1800+ 		} else  {
1801+ 			ZVAL_NULL (OBJ_PROP_NUM (obj , 1 ));
1802+ 		}
1803+ 
1804+ 		ZVAL_OBJ_COPY (OBJ_PROP_NUM (obj , 2 ), & intern -> std );
1805+ 
1806+ 		zend_hash_next_index_insert_new (Z_ARRVAL_P (return_value ), & zv );
1807+ 	} ZEND_HASH_FOREACH_END ();
1808+ 
1809+ 	zend_hash_destroy (& prefix_to_ns_table );
17741810}
17751811
17761812PHP_METHOD (DOM_Element , rename )
0 commit comments