@@ -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