Index: php_domxml.c =================================================================== RCS file: /repository/php4/ext/domxml/php_domxml.c,v retrieving revision 1.149 diff -u -b -r1.149 php_domxml.c --- php_domxml.c 3 May 2002 13:53:45 -0000 1.149 +++ php_domxml.c 4 May 2002 19:03:53 -0000 @@ -2015,7 +2067,7 @@ DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &node) == FAILURE) { - return; + RETURN_FALSE; } DOMXML_GET_OBJ(child, node, le_domxmlnodep); @@ -2025,24 +2077,73 @@ RETURN_FALSE; } +#if 0 if (NULL == (new_child = xmlCopyNode(child, 1))) { php_error(E_WARNING, "%s(): unable to clone node", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } +#endif + + /* Note this comment from libxml2::tree.c in xmlAddChild(): + * + * // If cur is a TEXT node, merge its content with adjacent TEXT nodes + * // cur is then freed. + * + * (cur is our "child" variable.) + * Because of this behaviour in libxml2 we have to unlink a TEXT node from + * our le_domxmlnodep before performing xmlAddChild() + * We get wrapper and handle in every case, b/c the TEXT node's to not have to be + * coalesced, which makes the handling a bit hackish: + * - remove a text node, always, b/c we cannot use the possible free'd memory + * - readd the node in case it has not been coalesced + * + * using xmlCopyNode() is bad, because your PHP code won't be able to freely + * store copies of a nodeID b/c it will be rendered invalid after each use of + * ->add_child() / ->append_child() + */ + if (child->type == XML_TEXT_NODE) { + zval **handle; + + if (zend_hash_index_find(Z_OBJPROP_P(node), 0, (void **)&handle) == FAILURE) { + php_error(E_WARNING, "%s() underlying object missing", get_active_function_name(TSRMLS_C)); + } + else + zend_list_delete(Z_LVAL_PP(handle)); + } /* FIXME reverted xmlAddChildList; crashes * Uwe: must have been a temporary problem. It works for me with both * xmlAddChildList and xmlAddChild */ // child = xmlAddSibling(nodep, new_child); - child = xmlAddChild(nodep, new_child); + new_child = xmlAddChild(nodep, child); - if (NULL == child) { + if (NULL == new_child) { php_error(E_WARNING, "%s(): couldn't append node", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } - DOMXML_RET_OBJ(rv, child, &ret); + /* check, if we have to readd the TEXT node to le_domxmlnodep + * because it has not been coalesced and free()d. + */ + if (new_child == child && child->type == XML_TEXT_NODE) { + /* readd TEXT node into list */ + php_dom_set_object(node, child, le_domxmltextp); + } + else if (new_child->type == XML_TEXT_NODE) { + /* the TEXT node has been coalesced and free()d; this makes zval *node[1] + * invalid. i'd like to prevent this magical invalidation of a node. and make node a reference + * to the new node created for new_child + */ +#if 0 + zval *newnode; + DOMXML_DOMOBJ_NEW(newnode, new_child, &ret); + DOMXML_RET_ZVAL(newnode); + return; +#endif + } + + DOMXML_RET_OBJ(rv, new_child, &ret); } /* }}} */