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 15:25:56 -0000 @@ -215,6 +215,7 @@ PHP_FE(domxml_node_has_attributes, NULL) PHP_FE(domxml_node_new_child, NULL) PHP_FE(domxml_node, NULL) + PHP_FE(domxml_text_node, NULL) PHP_FE(domxml_node_unlink_node, NULL) PHP_FE(domxml_node_set_content, NULL) PHP_FE(domxml_node_get_content, NULL) @@ -278,6 +279,8 @@ /* PHP_FALIAS(children, domxml_node_children, NULL) */ PHP_FALIAS(root, domxml_doc_document_element, NULL) PHP_FALIAS(add_root, domxml_add_root, NULL) + PHP_FALIAS(set_root, domxml_set_root, NULL) + PHP_FALIAS(get_root, domxml_get_root, NULL) PHP_FALIAS(imported_node, domxml_doc_imported_node, NULL) PHP_FALIAS(dtd, domxml_intdtd, NULL) PHP_FALIAS(ids, domxml_doc_ids, NULL) @@ -354,6 +357,7 @@ PHP_FALIAS(get_content, domxml_node_get_content, NULL) PHP_FALIAS(text_concat, domxml_node_text_concat, NULL) PHP_FALIAS(set_name, domxml_node_set_name, NULL) + PHP_FALIAS(path, domxml_node_get_path, NULL) PHP_FALIAS(is_blank_node, domxml_is_blank_node, NULL) PHP_FALIAS(dump_node, domxml_dump_node, NULL) {NULL, NULL, NULL} @@ -1567,6 +1571,34 @@ } /* }}} */ +static void php_textnode_new(INTERNAL_FUNCTION_PARAMETERS, xmlDocPtr docp) +{ + zval *rv; + xmlNode *node; + int ret, content_len; + char *content; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &content, &content_len) == FAILURE) { + return; + } + + node = xmlNewTextLen(content, content_len); + if (!node) { + RETURN_FALSE; + } + node->doc = docp; + + DOMXML_RET_OBJ(rv, node, &ret); +} + +/* {{{ proto object domxml_text_node(string content) + Creates node */ +PHP_FUNCTION(domxml_text_node) +{ + php_textnode_new(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL); +} +/* }}} */ + /* {{{ proto object domxml_node_name(void) Returns name of node */ PHP_FUNCTION(domxml_node_name) @@ -1894,6 +1926,26 @@ } /* }}} */ +/* {{{ proto string domxml_node_get_path(void) + Returns the path of the node in the document */ +PHP_FUNCTION(domxml_node_get_path) +{ + zval *id; + xmlNode *nodep; + xmlChar *path; + + DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep); + + DOMXML_NO_ARGS(); + + path = xmlGetNodePath(nodep); + if (!path) { + RETURN_FALSE; + } + RETVAL_STRING((char *)path, 1); + xmlFree(path); +} + /* {{{ proto object domxml_node_parent(void) Returns parent of node */ PHP_FUNCTION(domxml_node_parent) @@ -2025,24 +2077,64 @@ 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, *wrapper; + + wrapper = dom_object_get_data(child); + if (wrapper) { + if (zend_hash_index_find(Z_OBJPROP_P(wrapper), 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) { + zval *wrapper; + wrapper = php_domobject_new(child, &ret TSRMLS_CC); + } + + DOMXML_RET_OBJ(rv, new_child, &ret); } /* }}} */ @@ -2952,25 +3044,11 @@ Creates new text node */ PHP_FUNCTION(domxml_doc_create_text_node) { - zval *id, *rv; - xmlNode *node; + zval *id; xmlDocPtr docp; - int ret, content_len; - char *content; DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &content, &content_len) == FAILURE) { - return; - } - - node = xmlNewTextLen(content, content_len); - if (!node) { - RETURN_FALSE; - } - node->doc = docp; - - DOMXML_RET_OBJ(rv, node, &ret); + php_textnode_new(INTERNAL_FUNCTION_PARAM_PASSTHRU, docp); } /* }}} */ @@ -3534,6 +3612,47 @@ xmlDocSetRootElement(docp, nodep); DOMXML_RET_OBJ(rv, nodep, &ret); +} +/* }}} */ + +/* {{{ proto bool domxml_get_root(int domnode) + Gets root node of document */ +PHP_FUNCTION(domxml_get_root) +{ + zval *id, *rv; + xmlDoc *docp; + xmlNode *root; + int ret; + + DOMXML_PARAM_NONE(docp, id, le_domxmldocp); + + root = xmlDocGetRootElement(docp); + if (!root) { + RETURN_FALSE; + } + + DOMXML_RET_OBJ(rv, root, &ret); +} +/* }}} */ + +/* {{{ proto bool domxml_set_root(int domnode) + Sets root node of document */ +PHP_FUNCTION(domxml_set_root) +{ + zval *id, *rv, *node; + xmlDoc *docp; + xmlNode *root; + + DOMXML_PARAM_TWO(docp, id, le_domxmldocp, "o", &node, &rv); + DOMXML_GET_OBJ(root, node, le_domxmlnodep); + + if (!root) { + RETURN_FALSE; + } + + xmlDocSetRootElement(docp, root); + + RETURN_TRUE; } /* }}} */