diff -upr php-4.1.2/ext/domxml/config.m4 php-4.1.2-dom-xslt/ext/domxml/config.m4 --- php-4.1.2/ext/domxml/config.m4 Thu Oct 4 08:42:45 2001 +++ php-4.1.2-dom-xslt/ext/domxml/config.m4 Fri Jan 18 08:58:47 2002 @@ -1,5 +1,6 @@ -dnl $Id$ -dnl config.m4 for extension domxml +dnl +dnl $Id$ +dnl AC_DEFUN(PHP_DOM_CHECK_VERSION,[ old_CPPFLAGS=$CPPFLAGS @@ -20,17 +21,16 @@ AC_DEFUN(PHP_DOM_CHECK_VERSION,[ PHP_ARG_WITH(dom, for DOM support, [ --with-dom[=DIR] Include DOM support (requires libxml >= 2.4.2). - DIR is the libxml install directory, - defaults to /usr.]) + DIR is the libxml install directory.]) if test "$PHP_DOM" != "no"; then DOMXML_DIR_ADD="" - if test -r $PHP_DOM/include/libxml/tree.h; then - DOMXML_DIR=$PHP_DOM - elif test -r $PHP_DOM/include/libxml2/libxml/tree.h; then + if test -r $PHP_DOM/include/libxml2/libxml/tree.h; then DOMXML_DIR=$PHP_DOM DOMXML_DIR_ADD="/libxml2" + elif test -r $PHP_DOM/include/libxml/tree.h; then + DOMXML_DIR=$PHP_DOM else for i in /usr/local /usr; do test -r $i/include/libxml/tree.h && DOMXML_DIR=$i @@ -63,4 +63,110 @@ if test "$PHP_DOM" != "no"; then AC_DEFINE(HAVE_DOMXML,1,[ ]) PHP_EXTENSION(domxml, $ext_shared) PHP_SUBST(DOMXML_SHARED_LIBADD) +fi + +AC_DEFUN(PHP_DOM_XSLT_CHECK_VERSION,[ + old_CPPFLAGS=$CPPFLAGS + CPPFLAGS=-I$DOMXSLT_DIR/include + AC_MSG_CHECKING(for libxslt version) + AC_EGREP_CPP(yes,[ + #include + #if LIBXSLT_VERSION >= 10003 + yes + #endif + ],[ + AC_MSG_RESULT(>= 1.0.3) + ],[ + AC_MSG_ERROR(libxslt version 1.0.3 or greater required.) + ]) + CPPFLAGS=$old_CPPFLAGS +]) + +AC_DEFUN(PHP_DOM_EXSLT_CHECK_VERSION,[ + old_CPPFLAGS=$CPPFLAGS + CPPFLAGS=-I$DOMEXSLT_DIR/include + AC_MSG_CHECKING(for libexslt version) + AC_EGREP_CPP(yes,[ + #include + #if LIBEXSLT_VERSION >= 600 + yes + #endif + ],[ + AC_MSG_RESULT(>= 1.0.3) + ],[ + AC_MSG_ERROR(libxslt version 1.0.3 or greater required.) + ]) + CPPFLAGS=$old_CPPFLAGS +]) + +PHP_ARG_WITH(dom-xslt, for DOM XSLT support, +[ --with-dom-xslt[=DIR] Include DOM XSLT support (requires libxslt >= 1.0.3). + DIR is the libxslt install directory.]) + +PHP_ARG_WITH(dom-exslt, for DOM EXSLT support, +[ --with-dom-exslt[=DIR] Include DOM EXSLT support (requires libxslt >= 1.0.3). + DIR is the libexslt install directory.]) + +if test "$PHP_DOM_XSLT" != "no"; then + + if test -r $PHP_DOM_XSLT/include/libxslt/transform.h; then + DOMXSLT_DIR=$PHP_DOM_XSLT + else + for i in /usr/local /usr; do + test -r $i/include/libxslt/transform.h && DOMXSLT_DIR=$i + done + fi + + if test -z "$DOMXSLT_DIR"; then + AC_MSG_RESULT(not found) + AC_MSG_ERROR(Please reinstall the libxslt >= 1.0.3 distribution) + fi + + PHP_DOM_XSLT_CHECK_VERSION + + PHP_ADD_LIBRARY_WITH_PATH(xslt, $DOMXSLT_DIR/lib, DOMXML_SHARED_LIBADD) + + PHP_ADD_INCLUDE($DOMXSLT_DIR/include) + + if test "$PHP_DOM" = "no"; then + AC_MSG_ERROR(DOMXSLT requires DOMXML. Use --with-dom=) + fi + + AC_DEFINE(HAVE_DOMXSLT,1,[ ]) + + PHP_SUBST(DOMXML_SHARED_LIBADD) +fi + +if test "$PHP_DOM_EXSLT" != "no"; then + if test "$PHP_DOM" = "no"; then + AC_MSG_ERROR(DOMEXSLT requires DOMXML. Use --with-dom=) + fi + + if test "$PHP_DOM_XSLT" = "no"; then + AC_MSG_ERROR(DOMEXSLT requires DOMXSLT. Use --with-dom-xslt=) + fi + + if test -r $PHP_DOM_EXSLT/include/libexslt/exslt.h; then + DOMEXSLT_DIR=$PHP_DOM_EXSLT + else + for i in /usr/local /usr; do + test -r $i/include/libexslt/exslt.h && DOMEXSLT_DIR=$i + done + fi + + if test -z "$DOMEXSLT_DIR"; then + AC_MSG_RESULT(not found) + AC_MSG_ERROR(Please reinstall the libxslt >= 1.0.3 distribution) + fi + + PHP_DOM_EXSLT_CHECK_VERSION + + PHP_ADD_LIBRARY_WITH_PATH(exslt, $DOMEXSLT_DIR/lib, DOMXML_SHARED_LIBADD) + + PHP_ADD_INCLUDE($DOMEXSLT_DIR/include) + + AC_DEFINE(HAVE_DOMEXSLT,1,[ ]) + + PHP_SUBST(DOMXML_SHARED_LIBADD) + fi diff -upr php-4.1.2/ext/domxml/php_domxml.c php-4.1.2-dom-xslt/ext/domxml/php_domxml.c --- php-4.1.2/ext/domxml/php_domxml.c Fri Dec 14 11:45:46 2001 +++ php-4.1.2-dom-xslt/ext/domxml/php_domxml.c Tue Feb 26 17:03:46 2002 @@ -16,7 +16,11 @@ +----------------------------------------------------------------------+ */ -/* $Id$ */ +/* $Id$ */ + +/* TODO + * - Support Notation Nodes + * */ #ifdef HAVE_CONFIG_H @@ -33,7 +37,7 @@ /* General macros used by domxml */ #define DOMXML_DOMOBJ_NEW(zval, obj, ret) if (NULL == (zval = php_domobject_new(obj, ret TSRMLS_CC))) { \ - php_error(E_WARNING, "%s() cannot create required DOM object", \ + php_error(E_WARNING, "%s(): cannot create required DOM object", \ get_active_function_name(TSRMLS_C)); \ RETURN_FALSE; \ } @@ -46,13 +50,13 @@ DOMXML_RET_ZVAL(zval); #define DOMXML_GET_THIS(zval) if (NULL == (zval = getThis())) { \ - php_error(E_WARNING, "%s() underlying object missing", \ + php_error(E_WARNING, "%s(): underlying object missing", \ get_active_function_name(TSRMLS_C)); \ RETURN_FALSE; \ } #define DOMXML_GET_OBJ(ret, zval, le) if (NULL == (ret = php_dom_get_object(zval, le, 0 TSRMLS_CC))) { \ - php_error(E_WARNING, "%s() cannot fetch DOM object", \ + php_error(E_WARNING, "%s(): cannot fetch DOM object", \ get_active_function_name(TSRMLS_C)); \ RETURN_FALSE; \ } @@ -80,6 +84,17 @@ } \ DOMXML_GET_OBJ(ret, zval, le); +#define DOMXML_PARAM_ONE(ret, zval, le, s, p1) if (NULL == (zval = getThis())) { \ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o"s, &zval, p1) == FAILURE) { \ + return; \ + } \ + } else { \ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, s, p1) == FAILURE) { \ + return; \ + } \ + } \ + DOMXML_GET_OBJ(ret, zval, le); + #define DOMXML_PARAM_TWO(ret, zval, le, s, p1, p2) if (NULL == (zval = getThis())) { \ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o"s, &zval, p1, p2) == FAILURE) { \ return; \ @@ -91,6 +106,18 @@ } \ DOMXML_GET_OBJ(ret, zval, le); +#define DOMXML_PARAM_THREE(ret, zval, le, s, p1, p2, p3) if (NULL == (zval = getThis())) { \ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o"s, &zval, p1, p2, p3) == FAILURE) { \ + return; \ + } \ + } else { \ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, s, p1, p2, p3) == FAILURE) { \ + return; \ + } \ + } \ + DOMXML_GET_OBJ(ret, zval, le); + + #define DOMXML_PARAM_FOUR(ret, zval, le, s, p1, p2, p3, p4) if (NULL == (zval = getThis())) { \ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o"s, &zval, p1, p2, p3, p4) == FAILURE) { \ return; \ @@ -102,6 +129,7 @@ } \ DOMXML_GET_OBJ(ret, zval, le); + static int le_domxmldocp; static int le_domxmldoctypep; static int le_domxmldtdp; @@ -116,6 +144,9 @@ static int le_domxmlnotationp; /*static int le_domxmlentityp;*/ static int le_domxmlentityrefp; /*static int le_domxmlnsp;*/ +#if HAVE_DOMXSLT +static int le_domxsltstylesheetp; +#endif #if defined(LIBXML_XPATH_ENABLED) static int le_xpathctxp; @@ -140,6 +171,9 @@ zend_class_entry *domxmlns_class_entry; zend_class_entry *xpathctx_class_entry; zend_class_entry *xpathobject_class_entry; #endif +#if HAVE_DOMXSLT +zend_class_entry *domxsltstylesheet_class_entry; +#endif static int node_attributes(zval **attributes, xmlNode *nodep TSRMLS_DC); @@ -149,28 +183,48 @@ static zend_function_entry domxml_functi PHP_FE(domxml_version, NULL) PHP_FE(xmldoc, NULL) PHP_FE(xmldocfile, NULL) +#if defined(LIBXML_HTML_ENABLED) + PHP_FE(html_doc, NULL) + PHP_FE(html_doc_file, NULL) +#endif PHP_FE(xmltree, NULL) + PHP_FE(domxml_substitute_entities_default, NULL) PHP_FE(domxml_add_root, NULL) - PHP_FE(domxml_dumpmem, NULL) + PHP_FE(domxml_dump_mem, NULL) + PHP_FE(domxml_dump_mem_file, NULL) + PHP_FE(domxml_dump_node, NULL) +#if defined(LIBXML_HTML_ENABLED) + PHP_FE(domxml_html_dump_mem, NULL) +#endif PHP_FE(domxml_node_attributes, NULL) PHP_FE(domxml_elem_get_attribute, NULL) PHP_FE(domxml_elem_set_attribute, NULL) PHP_FE(domxml_node_children, NULL) + PHP_FE(domxml_node_has_attributes, NULL) PHP_FE(domxml_node_new_child, NULL) PHP_FE(domxml_node, NULL) PHP_FE(domxml_node_unlink_node, NULL) PHP_FE(domxml_node_set_content, NULL) + PHP_FE(domxml_node_get_content, NULL) PHP_FE(domxml_new_xmldoc, NULL) #if defined(LIBXML_XPATH_ENABLED) PHP_FE(xpath_new_context, NULL) PHP_FE(xpath_eval, NULL) PHP_FE(xpath_eval_expression, NULL) + PHP_FE(xpath_register_ns, NULL) #endif #if defined(LIBXML_XPTR_ENABLED) PHP_FE(xptr_new_context, NULL) PHP_FE(xptr_eval, NULL) #endif +#if HAVE_DOMXSLT + PHP_FE(domxml_xslt_version, NULL) + PHP_FE(domxml_xslt_stylesheet, NULL) + PHP_FE(domxml_xslt_stylesheet_doc, NULL) + PHP_FE(domxml_xslt_stylesheet_file, NULL) + PHP_FE(domxml_xslt_process, NULL) +#endif PHP_FALIAS(domxml_root, domxml_doc_document_element, NULL) PHP_FALIAS(domxml_attributes, domxml_node_attributes, NULL) @@ -183,6 +237,8 @@ static zend_function_entry domxml_functi PHP_FALIAS(domxml_unlink_node, domxml_node_unlink_node, NULL) PHP_FALIAS(set_content, domxml_node_set_content, NULL) PHP_FALIAS(new_xmldoc, domxml_new_xmldoc, NULL) + PHP_FALIAS(domxml_dumpmem, domxml_dump_mem, NULL) + {NULL, NULL, NULL} }; @@ -206,7 +262,12 @@ static function_entry php_domxmldoc_clas PHP_FALIAS(add_root, domxml_add_root, NULL) PHP_FALIAS(imported_node, domxml_doc_imported_node, NULL) PHP_FALIAS(dtd, domxml_intdtd, NULL) - PHP_FALIAS(dumpmem, domxml_dumpmem, NULL) + PHP_FALIAS(dumpmem, domxml_dump_mem, NULL) + PHP_FALIAS(dump_mem, domxml_dump_mem, NULL) + PHP_FALIAS(dump_mem_file, domxml_dump_mem_file, NULL) +#if defined(LIBXML_HTML_ENABLED) + PHP_FALIAS(html_dump_mem, domxml_html_dump_mem, NULL) +#endif #if defined(LIBXML_XPATH_ENABLED) PHP_FALIAS(xpath_init, xpath_init, NULL) PHP_FALIAS(xpath_new_context, xpath_new_context, NULL) @@ -217,13 +278,13 @@ static function_entry php_domxmldoc_clas static function_entry php_domxmldoctype_class_functions[] = { PHP_FALIAS(name, domxml_doctype_name, NULL) -/* +/* PHP_FALIAS(entities, domxml_doctype_entities, NULL) PHP_FALIAS(notations, domxml_doctype_notations, NULL) PHP_FALIAS(system_id, domxml_doctype_system_id, NULL) PHP_FALIAS(public_id, domxml_doctype_public_id, NULL) PHP_FALIAS(internal_subset, domxml_doctype_internal_subset, NULL) -*/ +*/ {NULL, NULL, NULL} }; @@ -249,16 +310,20 @@ static zend_function_entry php_domxmlnod PHP_FALIAS(owner_document, domxml_node_owner_document, NULL) PHP_FALIAS(new_child, domxml_node_new_child, NULL) PHP_FALIAS(attributes, domxml_node_attributes, NULL) + PHP_FALIAS(has_attributes, domxml_node_has_attributes, NULL) PHP_FALIAS(node, domxml_node, NULL) PHP_FALIAS(unlink, domxml_node_unlink_node, NULL) + PHP_FALIAS(replace_node, domxml_node_replace_node, NULL) PHP_FALIAS(set_content, domxml_node_set_content, NULL) + 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(node_name, domxml_node_name, NULL) PHP_FALIAS(node_type, domxml_node_type, NULL) PHP_FALIAS(node_value, domxml_node_value, NULL) PHP_FALIAS(clone_node, domxml_clone_node, NULL) - PHP_FALIAS(is_blank_node, domxml_is_blank_node, NULL) + PHP_FALIAS(is_blank_node, domxml_is_blank_node, NULL) + PHP_FALIAS(dump_node, domxml_dump_node, NULL) {NULL, NULL, NULL} }; @@ -299,7 +364,7 @@ static zend_function_entry php_domxmlent }; static zend_function_entry php_domxmlentity_class_functions[] = { -/* +/* PHP_FALIAS(public_id, domxml_entity_public_id, NULL) PHP_FALIAS(system_id, domxml_entity_system_id, NULL) PHP_FALIAS(notation_name, domxml_entity_notation_name, NULL) @@ -317,6 +382,7 @@ static zend_function_entry php_domxmlpi_ static zend_function_entry php_xpathctx_class_functions[] = { PHP_FALIAS(xpath_eval, xpath_eval, NULL) PHP_FALIAS(xpath_eval_expression, xpath_eval_expression, NULL) + PHP_FALIAS(xpath_register_ns, xpath_register_ns, NULL) {NULL, NULL, NULL} }; @@ -329,7 +395,7 @@ static zend_function_entry php_domxmlatt PHP_FALIAS(name, domxml_attr_name, NULL) PHP_FALIAS(value, domxml_attr_value, NULL) PHP_FALIAS(specified, domxml_attr_specified, NULL) -/* +/* PHP_FALIAS(owner_element, domxml_attr_owner_element, NULL) */ {NULL, NULL, NULL} @@ -339,8 +405,16 @@ static zend_function_entry php_domxmlns_ {NULL, NULL, NULL} }; +#if HAVE_DOMXSLT +static zend_function_entry php_domxsltstylesheet_class_functions[] = { +/* TODO: maybe some more methods? */ + PHP_FALIAS(process, domxml_xslt_process, NULL) + {NULL, NULL, NULL} +}; +#endif + zend_module_entry domxml_module_entry = { - STANDARD_MODULE_HEADER, + STANDARD_MODULE_HEADER, "domxml", domxml_functions, PHP_MINIT(domxml), @@ -348,7 +422,7 @@ zend_module_entry domxml_module_entry = PHP_RINIT(domxml), NULL, PHP_MINFO(domxml), - NO_VERSION_YET, + NO_VERSION_YET, STANDARD_MODULE_PROPERTIES }; @@ -370,14 +444,14 @@ static void dom_object_set_data(void *ob static zval *dom_object_get_data(void *obj) { -/* +/* char tmp[20]; sprintf(tmp, "%08X", obj); fprintf(stderr, "Trying getting %s from object ...", tmp); if(((xmlNodePtr) obj)->_private) fprintf(stderr, " found\n"); else - fprintf(stderr, " not found\n"); + fprintf(stderr, " not found\n"); */ return ((zval *) (((xmlNodePtr) obj)->_private)); } @@ -411,9 +485,14 @@ static inline void node_list_wrapper_dto { while (node != NULL) { node_list_wrapper_dtor(node->children); - // FIXME temporary fix; think of something better - if (node->type != XML_ATTRIBUTE_DECL && node->type != XML_DTD_NODE) { - attr_list_wrapper_dtor(node->properties); + switch (node->type) { + /* Skip property freeing for the following types */ + case XML_ATTRIBUTE_DECL: + case XML_DTD_NODE: + case XML_ENTITY_DECL: + break; + default: + attr_list_wrapper_dtor(node->properties); } node_wrapper_dtor(node); node = node->next; @@ -474,6 +553,92 @@ static void php_free_xpath_object(zend_r #endif +#if HAVE_DOMXSLT +static void php_free_xslt_stylesheet(zend_rsrc_list_entry *rsrc TSRMLS_DC) +{ + xsltStylesheetPtr sheet = (xsltStylesheetPtr) rsrc->ptr; + + if (sheet) { + node_wrapper_dtor((xmlNodePtr) sheet); + xsltFreeStylesheet(sheet); + } +} + +static void xsltstylesheet_set_data(void *obj, zval *wrapper) +{ +/* + char tmp[20]; + sprintf(tmp, "%08X", obj); + fprintf(stderr, "Adding %s to hash\n", tmp); +*/ + ((xsltStylesheetPtr) obj)->_private = wrapper; +} + + +static zval *xsltstylesheet_get_data(void *obj) +{ +/* + char tmp[20]; + sprintf(tmp, "%08X", obj); + fprintf(stderr, "Trying getting %s from object ...", tmp); + if(((xmlNodePtr) obj)->_private) + fprintf(stderr, " found\n"); + else + fprintf(stderr, " not found\n"); +*/ + return ((zval *) (((xsltStylesheetPtr) obj)->_private)); +} + +void *php_xsltstylesheet_get_object(zval *wrapper, int rsrc_type1, int rsrc_type2 TSRMLS_DC) +{ + void *obj; + zval **handle; + int type; + + if (NULL == wrapper) { + php_error(E_WARNING, "xsltstylesheet_get_object() invalid wrapper object passed"); + return NULL; + } + + if (Z_TYPE_P(wrapper) != IS_OBJECT) { + php_error(E_WARNING, "%s(): wrapper is not an object", get_active_function_name(TSRMLS_C)); + return NULL; + } + + 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)); + return NULL; + } + + obj = zend_list_find(Z_LVAL_PP(handle), &type); + if (!obj || ((type != rsrc_type1) && (type != rsrc_type2))) { + php_error(E_WARNING, "%s(): underlying object missing or of invalid type", get_active_function_name(TSRMLS_C)); + return NULL; + } + + return obj; +} + +static void php_xsltstylesheet_set_object(zval *wrapper, void *obj, int rsrc_type) +{ + zval *handle, *addr; + + MAKE_STD_ZVAL(handle); + Z_TYPE_P(handle) = IS_LONG; + Z_LVAL_P(handle) = zend_list_insert(obj, rsrc_type); + + MAKE_STD_ZVAL(addr); + Z_TYPE_P(addr) = IS_LONG; + Z_LVAL_P(addr) = (int) obj; + + zend_hash_index_update(Z_OBJPROP_P(wrapper), 0, &handle, sizeof(zval *), NULL); + zend_hash_index_update(Z_OBJPROP_P(wrapper), 1, &addr, sizeof(zval *), NULL); + zval_add_ref(&wrapper); + xsltstylesheet_set_data(obj, wrapper); +} +#endif /* HAVE_DOMXSLT */ + + void *php_xpath_get_object(zval *wrapper, int rsrc_type1, int rsrc_type2 TSRMLS_DC) { void *obj; @@ -486,18 +651,18 @@ void *php_xpath_get_object(zval *wrapper } if (Z_TYPE_P(wrapper) != IS_OBJECT) { - php_error(E_WARNING, "%s() wrapper is not an object", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): wrapper is not an object", get_active_function_name(TSRMLS_C)); return NULL; } 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)); + php_error(E_WARNING, "%s(): underlying object missing", get_active_function_name(TSRMLS_C)); return NULL; } obj = zend_list_find(Z_LVAL_PP(handle), &type); if (!obj || ((type != rsrc_type1) && (type != rsrc_type2))) { - php_error(E_WARNING, "%s() underlying object missing or of invalid type", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): underlying object missing or of invalid type", get_active_function_name(TSRMLS_C)); return NULL; } @@ -507,7 +672,7 @@ void *php_xpath_get_object(zval *wrapper static void xpath_object_set_data(void *obj, zval *wrapper) { -/* +/* char tmp[20]; sprintf(tmp, "%08X", obj); fprintf(stderr, "Adding %s to hash\n", tmp); @@ -518,12 +683,12 @@ static void xpath_object_set_data(void * static zval *xpath_object_get_data(void *obj) { -/* +/* char tmp[20]; sprintf(tmp, "%08X", obj); - fprintf(stderr, "Trying getting %s from hash ...", tmp); + fprintf(stderr, "Trying getting %s from hash ...", tmp); if(((xmlXPathObjectPtr) obj)->user) - fprintf(stderr, " found\n"); + fprintf(stderr, " found\n"); else fprintf(stderr, " not found\n"); */ @@ -574,7 +739,7 @@ static zval *php_xpathobject_new(xmlXPat /* rsrc_type = le_xpathobjectp; - php_xpath_set_object(wrapper, (void *) obj, rsrc_type); + php_xpath_set_object(wrapper, (void *) obj, rsrc_type); */ php_xpath_set_object(wrapper, (void *) obj, le_xpathobjectp); @@ -594,19 +759,19 @@ void *php_xpath_get_context(zval *wrappe } if (Z_TYPE_P(wrapper) != IS_OBJECT) { - php_error(E_WARNING, "%s() wrapper is not an object", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): wrapper is not an object", get_active_function_name(TSRMLS_C)); return NULL; } 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)); + php_error(E_WARNING, "%s(): underlying object missing", get_active_function_name(TSRMLS_C)); return NULL; } obj = zend_list_find(Z_LVAL_PP(handle), &type); if (!obj || ((type != rsrc_type1) && (type != rsrc_type2))) { - php_error(E_WARNING, "%s() Underlying object missing or of invalid type", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): underlying object missing or of invalid type", get_active_function_name(TSRMLS_C)); return NULL; } @@ -628,9 +793,9 @@ static zval *xpath_context_get_data(void /* char tmp[20]; sprintf(tmp, "%08X", obj); - fprintf(stderr, "Trying getting %s from hash ...", tmp); + fprintf(stderr, "Trying getting %s from hash ...", tmp); if(((xmlXPathContextPtr) obj)->user) - fprintf(stderr, " found\n"); + fprintf(stderr, " found\n"); else fprintf(stderr, " not found\n"); */ @@ -661,7 +826,7 @@ static zval *php_xpathcontext_new(xmlXPa int rsrc_type; if (! found) { - *found = 0; + *found = 0; } if (!obj) { @@ -677,8 +842,8 @@ static zval *php_xpathcontext_new(xmlXPa } MAKE_STD_ZVAL(wrapper); -/* - fprintf(stderr, "Adding new XPath Context\n"); +/* + fprintf(stderr, "Adding new XPath Context\n"); */ object_init_ex(wrapper, xpathctx_class_entry); rsrc_type = le_xpathctxp; @@ -700,12 +865,12 @@ void *php_dom_get_object(zval *wrapper, } if (Z_TYPE_P(wrapper) != IS_OBJECT) { - php_error(E_WARNING, "%s() wrapper is not an object", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): wrapper is not an object", get_active_function_name(TSRMLS_C)); return NULL; } 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)); + php_error(E_WARNING, "%s(): underlying object missing", get_active_function_name(TSRMLS_C)); return NULL; } @@ -713,7 +878,7 @@ void *php_dom_get_object(zval *wrapper, /* The following test should be replaced with search in all parents */ if (!obj) { /* || ((type != rsrc_type1) && (type != rsrc_type2))) { */ - php_error(E_WARNING, "%s() underlying object missing or of invalid type", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): underlying object missing or of invalid type", get_active_function_name(TSRMLS_C)); return NULL; } @@ -747,7 +912,7 @@ static zval *php_domobject_new(xmlNodePt int rsrc_type; if (! found) { - *found = 0; + *found = 0; } if (!obj) { @@ -795,8 +960,10 @@ static zval *php_domobject_new(xmlNodePt object_init_ex(wrapper, domxmlcomment_class_entry); rsrc_type = le_domxmlcommentp; content = xmlNodeGetContent(nodep); - if (content) + if (content) { + add_property_long(wrapper, "type", Z_TYPE_P(nodep)); add_property_stringl(wrapper, "content", (char *) content, strlen(content), 1); + } break; } @@ -817,7 +984,6 @@ static zval *php_domobject_new(xmlNodePt xmlNodePtr nodep = obj; object_init_ex(wrapper, domxmlentityref_class_entry); rsrc_type = le_domxmlentityrefp; - content = xmlNodeGetContent(nodep); add_property_stringl(wrapper, "name", (char *) nodep->name, strlen(nodep->name), 1); break; } @@ -851,8 +1017,10 @@ static zval *php_domobject_new(xmlNodePt } case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: { xmlDocPtr docp = (xmlDocPtr) obj; + object_init_ex(wrapper, domxmldoc_class_entry); rsrc_type = le_domxmldocp; if (docp->name) @@ -863,7 +1031,10 @@ static zval *php_domobject_new(xmlNodePt add_property_stringl(wrapper, "url", (char *) docp->URL, strlen(docp->URL), 1); else add_property_stringl(wrapper, "url", "", 0, 1); - add_property_stringl(wrapper, "version", (char *) docp->version, strlen(docp->version), 1); + if (docp->version) + add_property_stringl(wrapper, "version", (char *) docp->version, strlen(docp->version), 1); + else + add_property_stringl(wrapper, "version", "", 0, 1); if (docp->encoding) add_property_stringl(wrapper, "encoding", (char *) docp->encoding, strlen(docp->encoding), 1); add_property_long(wrapper, "standalone", docp->standalone); @@ -900,8 +1071,8 @@ static zval *php_domobject_new(xmlNodePt break; } - default: - php_error(E_WARNING, "%s() unsupported node type: %d\n", get_active_function_name(TSRMLS_C), Z_TYPE_P(obj)); + default: + php_error(E_WARNING, "%s(): unsupported node type: %d\n", get_active_function_name(TSRMLS_C), Z_TYPE_P(obj)); FREE_ZVAL(wrapper); return NULL; } @@ -911,6 +1082,17 @@ static zval *php_domobject_new(xmlNodePt } +static void domxml_error(void *ctx, const char *msg, ...) +{ + char buf[1024]; + va_list ap; + va_start(ap, msg); + vsnprintf(buf, 1024, msg, ap); + va_end(ap); + php_error(E_WARNING, buf); +} + + PHP_RINIT_FUNCTION(domxml) { return SUCCESS; @@ -932,12 +1114,12 @@ PHP_MINIT_FUNCTION(domxml) le_domxmlelementp = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domelement", module_number); le_domxmldtdp = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domdtd", module_number); le_domxmlcdatap = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domcdata", module_number); + le_domxmlentityrefp = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domentityref", module_number); + le_domxmlpip = zend_register_list_destructors_ex(php_free_xml_node, NULL, "dompi", module_number); /* Not yet initialized le_*s */ le_domxmldoctypep = -10000; - le_domxmlpip = -10002; le_domxmlnotationp = -10003; - le_domxmlentityrefp = -10004; #if defined(LIBXML_XPATH_ENABLED) le_xpathctxp = zend_register_list_destructors_ex(php_free_xpath_context, NULL, "xpathcontext", module_number); @@ -946,6 +1128,10 @@ PHP_MINIT_FUNCTION(domxml) /* le_domxmlnsp = register_list_destructors(NULL, NULL); */ +#if HAVE_DOMXSLT + le_domxsltstylesheetp = zend_register_list_destructors_ex(php_free_xslt_stylesheet, NULL, "xsltstylesheet", module_number); +#endif + INIT_OVERLOADED_CLASS_ENTRY(ce, "DomNode", php_domxmlnode_class_functions, NULL, NULL, NULL); domxmlnode_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); @@ -996,6 +1182,11 @@ PHP_MINIT_FUNCTION(domxml) xpathobject_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); #endif +#if HAVE_DOMXSLT + INIT_OVERLOADED_CLASS_ENTRY(ce, "XsltStylesheet", php_domxsltstylesheet_class_functions, NULL, NULL, NULL); + domxsltstylesheet_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); +#endif + REGISTER_LONG_CONSTANT("XML_ELEMENT_NODE", XML_ELEMENT_NODE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NODE", XML_ATTRIBUTE_NODE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XML_TEXT_NODE", XML_TEXT_NODE, CONST_CS | CONST_PERSISTENT); @@ -1040,6 +1231,15 @@ PHP_MINIT_FUNCTION(domxml) REGISTER_LONG_CONSTANT("XPATH_USERS", XPATH_USERS, CONST_CS | CONST_PERSISTENT); #endif + xmlSetGenericErrorFunc(xmlGenericErrorContext, (xmlGenericErrorFunc)domxml_error); +#if HAVE_DOMXSLT + xsltSetGenericErrorFunc(xsltGenericErrorContext, (xmlGenericErrorFunc)domxml_error); +#if HAVE_DOMEXSLT + exsltRegisterAll(); +#endif +#endif + + return SUCCESS; } @@ -1065,12 +1265,24 @@ PHP_MINFO_FUNCTION(domxml) php_info_print_table_start(); php_info_print_table_row(2, "DOM/XML", "enabled"); php_info_print_table_row(2, "libxml Version", LIBXML_DOTTED_VERSION); +#if defined(LIBXML_HTML_ENABLED) + php_info_print_table_row(2, "HTML Support", "enabled"); +#endif #if defined(LIBXML_XPATH_ENABLED) php_info_print_table_row(2, "XPath Support", "enabled"); #endif #if defined(LIBXML_XPTR_ENABLED) php_info_print_table_row(2, "XPointer Support", "enabled"); #endif +#if HAVE_DOMXSLT + php_info_print_table_row(2, "DOM/XSLT", "enabled"); + php_info_print_table_row(2, "libxslt Version", LIBXSLT_DOTTED_VERSION); +#if HAVE_DOMEXSLT + php_info_print_table_row(2, "DOM/EXSLT", "enabled"); + php_info_print_table_row(2, "libexslt Version", LIBEXSLT_DOTTED_VERSION); +#endif +#endif + php_info_print_table_end(); } @@ -1318,13 +1530,13 @@ PHP_FUNCTION(domxml_is_blank_node) PHP_FUNCTION(domxml_node_type) { zval *id; - xmlNode *n; + xmlNode *node; - DOMXML_GET_THIS_OBJ(n, id, le_domxmlnodep); + DOMXML_GET_THIS_OBJ(node, id, le_domxmlnodep); DOMXML_NO_ARGS(); - RETURN_LONG(Z_TYPE_P(n)); + RETURN_LONG(node->type); } /* }}} */ @@ -1533,7 +1745,7 @@ PHP_FUNCTION(domxml_node_parent) int ret; DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep); - + DOMXML_NO_ARGS(); last = nodep->parent; @@ -1558,7 +1770,7 @@ PHP_FUNCTION(domxml_node_children) /* Even if the nodep is a XML_DOCUMENT_NODE the type is at the same position. */ - if (Z_TYPE_P(nodep) == XML_DOCUMENT_NODE) + if ((Z_TYPE_P(nodep) == XML_DOCUMENT_NODE) || (Z_TYPE_P(nodep) == XML_HTML_DOCUMENT_NODE)) last = ((xmlDoc *) nodep)->children; else last = nodep->children; @@ -1579,32 +1791,27 @@ PHP_FUNCTION(domxml_node_children) } /* }}} */ -/* {{{ proto object domxml_node_unlink_node(void) - Deletes node */ +/* {{{ proto void domxml_node_unlink_node([object node]) + Deletes the node */ PHP_FUNCTION(domxml_node_unlink_node) { zval *id; xmlNode *nodep; - DOMXML_NO_ARGS(); - - DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep); - - DOMXML_NO_ARGS(); + DOMXML_PARAM_NONE(nodep, id, le_domxmlnodep); xmlUnlinkNode(nodep); xmlFreeNode(nodep); zval_dtor(id); /* This is not enough because the children won't be deleted */ - RETURN_TRUE; } /* }}} */ -/* {{{ proto object domxml_node_add_child(int domnode) +/* {{{ proto object domxml_node_add_child(object domnode) Adds existing node to parent node */ PHP_FUNCTION(domxml_node_add_child) { zval *id, *rv, *node; - xmlNodePtr child, nodep; + xmlNodePtr child, nodep, new_child; int ret; DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep); @@ -1615,10 +1822,20 @@ PHP_FUNCTION(domxml_node_add_child) DOMXML_GET_OBJ(child, node, le_domxmlnodep); - child = xmlAddChild(nodep, child); + if (child->type == XML_ATTRIBUTE_NODE) { + php_error(E_WARNING, "%s(): can't add attribute node", get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + + if (NULL == (new_child = xmlCopyNode(child, 1))) { + php_error(E_WARNING, "%s(): unable to clone node", get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + + child = xmlAddChild(nodep, new_child); if (NULL == child) { - php_error(E_WARNING, "%s() couldn't add child", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): couldn't add child", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } @@ -1626,12 +1843,39 @@ PHP_FUNCTION(domxml_node_add_child) } /* }}} */ -/* {{{ proto object domxml_node_append_child(int domnode) +/* {{{ proto object domxml_node_replace_node(object domnode) + Replaces one node with another node */ +PHP_FUNCTION(domxml_node_replace_node) +{ + zval *id, *rv, *node; + xmlNodePtr repnode, nodep, new_repnode; + int ret; + + DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &node) == FAILURE) { + return; + } + + DOMXML_GET_OBJ(repnode, node, le_domxmlnodep); + + if (NULL == (new_repnode = xmlCopyNode(repnode, 1))) { + php_error(E_WARNING, "%s(): unable to clone node", get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + + repnode = xmlReplaceNode(nodep, new_repnode); + + DOMXML_RET_OBJ(rv, repnode, &ret); +} +/* }}} */ + +/* {{{ proto object domxml_node_append_child(object domnode) Adds node to list of children */ PHP_FUNCTION(domxml_node_append_child) { zval *id, *rv, *node; - xmlNodePtr child, nodep; + xmlNodePtr child, nodep, new_child; int ret; DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep); @@ -1642,11 +1886,21 @@ PHP_FUNCTION(domxml_node_append_child) DOMXML_GET_OBJ(child, node, le_domxmlnodep); + if (child->type == XML_ATTRIBUTE_NODE) { + php_error(E_WARNING, "%s(): can't append attribute node", get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + + if (NULL == (new_child = xmlCopyNode(child, 1))) { + php_error(E_WARNING, "%s(): unable to clone node", get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + // FIXME reverted xmlAddChildList; crashes - child = xmlAddSibling(nodep, child); + child = xmlAddSibling(nodep, new_child); if (NULL == child) { - php_error(E_WARNING, "%s() couldn't add node", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): couldn't append node", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } @@ -1654,7 +1908,7 @@ PHP_FUNCTION(domxml_node_append_child) } /* }}} */ -/* {{{ proto object domxml_node_insert_before(int newnode, int refnode) +/* {{{ proto object domxml_node_insert_before(object newnode, object refnode) Adds node in list of nodes before given node */ PHP_FUNCTION(domxml_node_insert_before) { @@ -1674,7 +1928,7 @@ PHP_FUNCTION(domxml_node_insert_before) child = xmlAddPrevSibling(refp, child); if (NULL == child) { - php_error(E_WARNING, "%s() couldn't add newnode as the previous sibling of refnode", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): couldn't add newnode as the previous sibling of refnode", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } @@ -1783,11 +2037,35 @@ PHP_FUNCTION(domxml_node_set_content) /* FIXME: Actually the property 'content' of the node has to be updated as well. Since 'content' should disappear sooner or later and being replaces by a function 'content()' I skip this for now - */ + */ RETURN_TRUE; } /* }}} */ +/* {{{ proto string domxml_node_get_content() + Gets content of a node. + + "Read the value of a node, this can be either the text carried directly by +this node if it's a TEXT node or the aggregate string of the values carried by +this node child's (TEXT and ENTITY_REF). Entity references are substituted." + */ +PHP_FUNCTION(domxml_node_get_content) +{ + zval *id; + xmlNode *nodep; + xmlChar *mem; + + DOMXML_PARAM_NONE(nodep, id, le_domxmlnodep); + mem = xmlNodeGetContent(nodep); + if (!mem) { + RETURN_FALSE; + } + + RETURN_STRING(mem,1); +} +/* }}} */ + + /* End of Methods DomNode }}} */ @@ -1902,7 +2180,7 @@ PHP_FUNCTION(domxml_elem_set_attribute) attr = xmlSetProp(nodep, name, value); if (!attr) { - php_error(E_WARNING, "%s() no such attribute '%s'", get_active_function_name(TSRMLS_C), name); + php_error(E_WARNING, "%s(): no such attribute '%s'", get_active_function_name(TSRMLS_C), name); RETURN_FALSE; } @@ -1966,7 +2244,7 @@ PHP_FUNCTION(domxml_elem_set_attribute_n xmlAttr *attrp; DOMXML_NOT_IMPLEMENTED(); - + if ((ZEND_NUM_ARGS() == 1) && getParameters(ht, 1, &arg1) == SUCCESS) { id = getThis(); nodep = php_dom_get_object(id, le_domxmlelementp, 0 TSRMLS_CC); @@ -2052,8 +2330,8 @@ PHP_FUNCTION(domxml_doc_doctype) Returns DomeDOMImplementation */ PHP_FUNCTION(domxml_doc_implementation) { - zval *id; - xmlDocPtr docp; +/* zval *id; + xmlDocPtr docp;*/ DOMXML_NOT_IMPLEMENTED(); @@ -2283,7 +2561,7 @@ PHP_FUNCTION(domxml_doc_create_processin } /* }}} */ -/* {{{ proto object domxml_doc_imported_node(int node, bool recursive) +/* {{{ proto object domxml_doc_imported_node(object node, bool recursive) Creates new element node */ PHP_FUNCTION(domxml_doc_imported_node) { @@ -2311,7 +2589,7 @@ PHP_FUNCTION(domxml_doc_imported_node) } /* }}} */ -/* {{{ proto object domxml_dtd([int doc_handle]) +/* {{{ proto object domxml_dtd(void) Returns DTD of document */ PHP_FUNCTION(domxml_intdtd) { @@ -2331,9 +2609,9 @@ PHP_FUNCTION(domxml_intdtd) } /* }}} */ -/* {{{ proto string domxml_dumpmem([int doc_handle]) +/* {{{ proto string domxml_dump_mem([object doc_handle]) Dumps document into string */ -PHP_FUNCTION(domxml_dumpmem) +PHP_FUNCTION(domxml_dump_mem) { zval *id; xmlDoc *docp; @@ -2341,7 +2619,6 @@ PHP_FUNCTION(domxml_dumpmem) int size; DOMXML_PARAM_NONE(docp, id, le_domxmldocp); - xmlDocDumpMemory(docp, &mem, &size); if (!size) { RETURN_FALSE; @@ -2350,6 +2627,73 @@ PHP_FUNCTION(domxml_dumpmem) } /* }}} */ +/* {{{ proto int domxml_dump_mem_file([object doc_handle],filename,compressmode) + Dumps document into file and uses compression if specified + Returns false on error, otherwise the length of the xml-document (uncompressed) + */ +PHP_FUNCTION(domxml_dump_mem_file) +{ + zval *id; + xmlDoc *docp; + int file_len, bytes; + int compressmode = 0; + char *file; + DOMXML_PARAM_THREE(docp, id, le_domxmldocp, "s|l", &file, &file_len, &compressmode); + + xmlSetCompressMode (compressmode); + bytes = xmlSaveFile(file,docp); + if (bytes == -1) + { + RETURN_FALSE; + } + RETURN_LONG(bytes); +} +/* }}} */ + +/* {{{ proto string domxml_dump_node([object doc_handle],object node_handle[,int format[,int level]]) + Dumps node into string */ +PHP_FUNCTION(domxml_dump_node) +{ + zval *id, *nodep; + xmlDocPtr docp; + xmlNodePtr elementp; + xmlChar *mem ; + xmlBufferPtr buf; + int level = 0; + int format = 0; + + DOMXML_PARAM_THREE(docp, id, le_domxmldocp,"o|ll",&nodep,&format,&level); + + DOMXML_GET_OBJ(elementp, nodep, le_domxmlnodep); + + if (Z_TYPE_P(elementp) == XML_DOCUMENT_NODE || Z_TYPE_P(elementp) == XML_HTML_DOCUMENT_NODE ) { + php_error(E_WARNING, "%s(): cannot dump element with a document node", get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + + buf = xmlBufferCreate(); + if (!buf) + { + php_error(E_WARNING, "%s(): could fetch buffer", get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + + xmlNodeDump(buf, docp, elementp,level,format); + + mem = (xmlChar*) xmlBufferContent(buf); + + if (!mem) { + xmlBufferFree(buf); + RETURN_FALSE; + } + RETVAL_STRING(mem, 1); + + xmlBufferFree(buf); + +} +/* }}} */ + + /* {{{ proto object xmldoc(string xmldoc [, bool from_file]) Creates DOM object of XML document */ PHP_FUNCTION(xmldoc) @@ -2413,6 +2757,106 @@ PHP_FUNCTION(xmldocfile) } /* }}} */ +#if defined(LIBXML_HTML_ENABLED) +/* {{{ proto string domxml_html_dump_mem([int doc_handle]) + Dumps document into string as HTML */ +PHP_FUNCTION(domxml_html_dump_mem) +{ + zval *id; + xmlDoc *docp; + xmlChar *mem; + int size; + + DOMXML_PARAM_NONE(docp, id, le_domxmldocp); + + htmlDocDumpMemory(docp, &mem, &size); + if (!size) { + RETURN_FALSE; + } + RETURN_STRINGL(mem, size, 1); +} +/* }}} */ + +/* {{{ proto object html_doc(string html_doc [, bool from_file]) + Creates DOM object of HTML document */ +PHP_FUNCTION(html_doc) +{ + zval *rv; + xmlDoc *docp; + int ret; + char *buffer; + int buffer_len; + zend_bool from_file = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &buffer, &buffer_len, &from_file) == FAILURE) { + return; + } + + if (from_file) { + docp = htmlParseFile(buffer, NULL); + } else { + docp = htmlParseDoc(buffer, NULL); + } + if (!docp) + RETURN_FALSE; + + DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret); +} +/* }}} */ + +/* {{{ proto object html_doc_file(string filename) + Creates DOM object of HTML document in file */ +PHP_FUNCTION(html_doc_file) +{ + zval *rv; + xmlDoc *docp; + int ret, file_len; + char *file; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) { + return; + } + + docp = htmlParseFile(file, NULL); + if (!docp) { + RETURN_FALSE; + } + + DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret); + + add_property_resource(return_value, "doc", ret); + if (docp->name) + add_property_stringl(return_value, "name", (char *) docp->name, strlen(docp->name), 1); + if (docp->URL) + add_property_stringl(return_value, "url", (char *) docp->URL, strlen(docp->URL), 1); + if (docp->version) + add_property_stringl(return_value, "version", (char *) docp->version, strlen(docp->version), 1); +/* add_property_stringl(return_value, "version", (char *) docp->version, strlen(docp->version), 1);*/ + if (docp->encoding) + add_property_stringl(return_value, "encoding", (char *) docp->encoding, strlen(docp->encoding), 1); + add_property_long(return_value, "standalone", docp->standalone); + add_property_long(return_value, "type", Z_TYPE_P(docp)); + add_property_long(return_value, "compression", docp->compression); + add_property_long(return_value, "charset", docp->charset); + zend_list_addref(ret); +} +/* }}} */ +#endif /* defined(LIBXML_HTML_ENABLED) */ + +/* {{{ proto bool domxml_substitute_entities_default(bool enable) + Set and return the previous value for default entity support */ +PHP_FUNCTION(domxml_substitute_entities_default) +{ + zend_bool enable; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &enable) == FAILURE) { + return; + } + + RETURN_BOOL(xmlSubstituteEntitiesDefault(enable)); +} +/* }}} */ + /* {{{ proto bool domxml_node_text_concat(string content) Add string tocontent of a node */ PHP_FUNCTION(domxml_node_text_concat) @@ -2421,7 +2865,7 @@ PHP_FUNCTION(domxml_node_text_concat) xmlNode *nodep; char *content; int content_len; - + DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &content, &content_len) == FAILURE) { @@ -2589,7 +3033,7 @@ static int node_children(zval **children /* Get the namespace of the current node and add it as a property */ /* XXX FIXME XXX */ -/* +/* if(!node_namespace(&namespace, last)) zend_hash_update(Z_OBJPROP_P(child), "namespace", sizeof("namespace"), (void *) &namespace, sizeof(zval *), NULL); */ @@ -2619,7 +3063,7 @@ PHP_FUNCTION(xmltree) xmlNode *root; int ret, buf_len; char *buf; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) { return; } @@ -2690,7 +3134,7 @@ static void php_xpathptr_new_context(INT } /* }}} */ -/* {{{ proto string xpath_new_context([int doc_handle]) +/* {{{ proto object xpath_new_context([int doc_handle]) Creates new XPath context */ PHP_FUNCTION(xpath_new_context) { @@ -2698,7 +3142,7 @@ PHP_FUNCTION(xpath_new_context) } /* }}} */ -/* {{{ proto string xptr_new_context([int doc_handle]) +/* {{{ proto object xptr_new_context([int doc_handle]) Creates new XPath context */ PHP_FUNCTION(xptr_new_context) { @@ -2731,10 +3175,10 @@ static void php_xpathptr_eval(INTERNAL_F } ctxp = php_xpath_get_context(id, le_xpathctxp, 0 TSRMLS_CC); - if (!ctxp) { - php_error(E_WARNING, "%s() cannot fetch XPATH context", get_active_function_name(TSRMLS_C)); - RETURN_FALSE; - } + if (!ctxp) { + php_error(E_WARNING, "%s(): cannot fetch XPATH context", get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } if (contextnode) { DOMXML_GET_OBJ(contextnodep, contextnode, le_domxmlnodep); @@ -2761,7 +3205,7 @@ static void php_xpathptr_eval(INTERNAL_F } if (NULL == (rv = php_xpathobject_new(xpathobjp, &ret TSRMLS_CC))) { - php_error(E_WARNING, "%s() cannot create required XPATH objcet", get_active_function_name(TSRMLS_C)); + php_error(E_WARNING, "%s(): cannot create required XPATH objcet", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } SEPARATE_ZVAL(&rv); @@ -2836,7 +3280,7 @@ static void php_xpathptr_eval(INTERNAL_F } /* }}} */ -/* {{{ proto int xpath_eval([int xpathctx_handle,] string str) +/* {{{ proto object xpath_eval([object xpathctx_handle,] string str) Evaluates the XPath Location Path in the given string */ PHP_FUNCTION(xpath_eval) { @@ -2844,13 +3288,46 @@ PHP_FUNCTION(xpath_eval) } /* }}} */ -/* {{{ proto int xpath_eval_expression([int xpathctx_handle,] string str) - Evaluates the XPath Location Path in the given string */ +/* {{{ proto object xpath_eval_expression([object xpathctx_handle,] string str) + Evaluates the XPath expression in the given string */ PHP_FUNCTION(xpath_eval_expression) { php_xpathptr_eval(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_XPATH, 1); } /* }}} */ + +/* {{{ proto bool xpath_register_ns([object xpathctx_handle,] string namespace_prefix, string namespace_uri) + Registeres the given namespace in the passed XPath context */ +PHP_FUNCTION(xpath_register_ns) +{ + /* + TODO: + - automagically register all namespaces when creating a new context + */ + + int prefix_len, uri_len, result; + xmlXPathContextPtr ctxp; + char *prefix, *uri, *uri_static; + zval *id; + + DOMXML_PARAM_FOUR(ctxp, id, le_xpathctxp, "ss", &prefix, &prefix_len, &uri, &uri_len); + + /* set the context node to NULL - what is a context node anyway? */ + ctxp->node = NULL; + + /* + this is a hack - libxml2 doesn't copy the URI, it simply uses the string + given in the parameter - which is normally deallocated after the function + */ + uri_static = estrndup(uri, uri_len); + result = xmlXPathRegisterNs(ctxp, prefix, uri_static); + + if (0 == result) { + RETURN_TRUE; + } + RETURN_FALSE; +} +/* }}} */ #endif /* defined(LIBXML_XPATH_ENABLED) */ #if defined(LIBXML_XPTR_ENABLED) @@ -2864,12 +3341,266 @@ PHP_FUNCTION(xptr_eval) #endif /* LIBXML_XPTR_ENABLED */ /* {{{ proto string domxml_version(void) - Dumps document into string */ + Get XML library version */ PHP_FUNCTION(domxml_version) { RETURN_STRING(LIBXML_DOTTED_VERSION, 1); } /* }}} */ + +#if HAVE_DOMXSLT +static zval *php_xsltstylesheet_new(xsltStylesheetPtr obj, int *found TSRMLS_DC) +{ + zval *wrapper; + int rsrc_type; + + if (! found) { + *found = 0; + } + + if (!obj) { + MAKE_STD_ZVAL(wrapper); + ZVAL_NULL(wrapper); + return wrapper; + } + + if ((wrapper = (zval *) dom_object_get_data((void *) obj))) { + zval_add_ref(&wrapper); + *found = 1; + return wrapper; + } + + MAKE_STD_ZVAL(wrapper); + + object_init_ex(wrapper, domxsltstylesheet_class_entry); + rsrc_type = le_domxsltstylesheetp; + php_xsltstylesheet_set_object(wrapper, (void *) obj, rsrc_type); + + return (wrapper); +} + +/* {{{ proto object domxml_xslt_stylesheet(string xsltstylesheet) + Creates XSLT Stylesheet object from string */ +PHP_FUNCTION(domxml_xslt_stylesheet) +{ + zval *rv; + xmlDocPtr docp; + xsltStylesheetPtr sheetp; + int ret; + char *buffer; + int buffer_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buffer, &buffer_len) == FAILURE) { + RETURN_FALSE; + } + + docp = xmlParseDoc(buffer); + + if (!docp) + RETURN_FALSE; + + sheetp = xsltParseStylesheetDoc(docp); + + if (!sheetp) + RETURN_FALSE; + + rv = php_xsltstylesheet_new(sheetp, &ret TSRMLS_CC); + DOMXML_RET_ZVAL(rv); +} +/* }}} */ + +/* {{{ proto object domxml_xslt_stylesheet_doc(object xmldoc) + Creates XSLT Stylesheet object from DOM Document object */ +PHP_FUNCTION(domxml_xslt_stylesheet_doc) +{ + zval *rv, *idxml; + xmlDocPtr docp; + xmlDocPtr newdocp; + xsltStylesheetPtr sheetp; + int ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &idxml) == FAILURE) { + RETURN_FALSE; + } + + DOMXML_GET_OBJ(docp, idxml, le_domxmldocp); + + newdocp = xmlCopyDoc(docp, 1); + + if (!newdocp) + RETURN_FALSE; + + sheetp = xsltParseStylesheetDoc(newdocp); + + if (!sheetp) + RETURN_FALSE; + + rv = php_xsltstylesheet_new(sheetp, &ret TSRMLS_CC); + DOMXML_RET_ZVAL(rv); +} +/* }}} */ + +/* {{{ proto object domxml_xslt_stylesheet_file(string filename) + Creates XSLT Stylesheet object from file */ +PHP_FUNCTION(domxml_xslt_stylesheet_file) +{ + zval *rv; + xsltStylesheetPtr sheetp; + int ret, file_len; + char *file; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) { + RETURN_FALSE; + } + + sheetp = xsltParseStylesheetFile(file); + + if (!sheetp) + RETURN_FALSE; + + rv = php_xsltstylesheet_new(sheetp, &ret TSRMLS_CC); + DOMXML_RET_ZVAL(rv); +} +/* }}} */ + +/* {{{ php_domxslt_string_to_xpathexpr() + Translates a string to a XPath Expression */ +static char *php_domxslt_string_to_xpathexpr(const char *str) +{ + const xmlChar *string = (const xmlChar *)str; + + xmlChar *value; + + TSRMLS_FETCH(); + + if (xmlStrchr(string, '"')) { + if (xmlStrchr(string, '\'')) { + php_error(E_WARNING, "Cannot create XPath expression (string contains both quote and double-quotes) in %s", + get_active_function_name(TSRMLS_C)); + return NULL; + } + value = xmlStrdup((const xmlChar *)"'"); + value = xmlStrcat(value, string); + value = xmlStrcat(value, (const xmlChar *)"'"); + } + else { + value = xmlStrdup((const xmlChar *)"\""); + value = xmlStrcat(value, string); + value = xmlStrcat(value, (const xmlChar *)"\""); + } + + return (char *)value; +} + +/* {{{ php_domxslt_make_params() + Translates a PHP array to a libxslt parameters array */ +static char **php_domxslt_make_params(zval *idvars, int xpath_params) +{ + HashTable *parht; + int parsize; + zval **value; + char *xpath_expr, *string_key = NULL; + ulong num_key; + char **params = NULL; + int i = 0; + + TSRMLS_FETCH(); + + parht = HASH_OF(idvars); + parsize = (2 * zend_hash_num_elements(parht) + 1) * sizeof(char *); + params = (char **)emalloc(parsize); + memset((char *)params, 0, parsize); + + for (zend_hash_internal_pointer_reset(parht); + zend_hash_get_current_data(parht, (void **)&value) == SUCCESS; + zend_hash_move_forward(parht)) { + + if (zend_hash_get_current_key(parht, &string_key, &num_key, 1) != HASH_KEY_IS_STRING) { + php_error(E_WARNING, "Invalid argument or parameter array to %s", + get_active_function_name(TSRMLS_C)); + return NULL; + } + else { + SEPARATE_ZVAL(value); + convert_to_string_ex(value); + + if (!xpath_params) { + xpath_expr = php_domxslt_string_to_xpathexpr(Z_STRVAL_PP(value)); + } + else { + xpath_expr = Z_STRVAL_PP(value); + } + + if (xpath_expr) { + params[i++] = string_key; + params[i++] = xpath_expr; + } + } + } + + params[i++] = NULL; + + return params; +} + +/* {{{ proto object domxml_xslt_process(object xslstylesheet, object xmldoc [, array xslt_parameters [, bool xpath_parameters]]) + Perform an XSLT transformation */ +PHP_FUNCTION(domxml_xslt_process) +{ +/* TODO: + - test memory deallocation + - test other stuff + - check xsltsp->errors ??? +*/ + zval *rv, *idxsl, *idxml, *idparams = NULL; + zend_bool xpath_params = 0; + xsltStylesheetPtr xsltstp; + xmlDocPtr xmldocp; + xmlDocPtr docp; + char **params = NULL; + int ret; + + DOMXML_GET_THIS(idxsl); + + xsltstp = php_xsltstylesheet_get_object(idxsl, le_domxsltstylesheetp, 0 TSRMLS_CC); + if (!xsltstp) { + php_error(E_WARNING, "%s(): underlying object missing", + get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|ab", &idxml, &idparams, &xpath_params) == FAILURE) { + RETURN_FALSE; + } + + DOMXML_GET_OBJ(xmldocp, idxml, le_domxmldocp); + + if (idparams) { + params = php_domxslt_make_params(idparams, xpath_params); + } + + docp = xsltApplyStylesheet(xsltstp, xmldocp, (const char**)params); + + if (params) { + efree(params); + } + + if (!docp) { + RETURN_FALSE; + } + + DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret); +} +/* }}} */ + +/* {{{ proto string domxml_xslt_version(void) + Get XSLT library version */ +PHP_FUNCTION(domxml_xslt_version) +{ + RETURN_STRING(LIBXSLT_DOTTED_VERSION, 1); +} +/* }}} */ +#endif /* HAVE_DOMXSLT */ #endif /* HAVE_DOMXML */ diff -upr php-4.1.2/ext/domxml/php_domxml.h php-4.1.2-dom-xslt/ext/domxml/php_domxml.h --- php-4.1.2/ext/domxml/php_domxml.h Fri Dec 14 11:45:46 2001 +++ php-4.1.2-dom-xslt/ext/domxml/php_domxml.h Tue Jan 22 00:21:32 2002 @@ -16,19 +16,36 @@ +----------------------------------------------------------------------+ */ -/* $Id$ */ +/* $Id$ */ #ifndef PHP_DOMXML_H #define PHP_DOMXML_H #if HAVE_DOMXML #include +#include +#include +#if defined(LIBXML_HTML_ENABLED) +#include +#include +#endif #if defined(LIBXML_XPATH_ENABLED) #include +#include #endif #if defined(LIBXML_XPTR_ENABLED) #include #endif +#if HAVE_DOMXSLT +#include +#include +#include +#include +#if HAVE_DOMEXSLT +#include +#include +#endif +#endif extern zend_module_entry domxml_module_entry; #define domxml_module_ptr &domxml_module_entry @@ -40,8 +57,13 @@ PHP_MINFO_FUNCTION(domxml); PHP_FUNCTION(domxml_version); PHP_FUNCTION(xmldoc); PHP_FUNCTION(xmldocfile); +#if defined(LIBXML_HTML_ENABLED) +PHP_FUNCTION(html_doc); +PHP_FUNCTION(html_doc_file); +#endif PHP_FUNCTION(xmltree); PHP_FUNCTION(domxml_new_xmldoc); +PHP_FUNCTION(domxml_substitute_entities_default); /* Class Document methods */ PHP_FUNCTION(domxml_doc_doctype); @@ -57,7 +79,13 @@ PHP_FUNCTION(domxml_doc_create_entity_re PHP_FUNCTION(domxml_doc_imported_node); PHP_FUNCTION(domxml_add_root); PHP_FUNCTION(domxml_intdtd); -PHP_FUNCTION(domxml_dumpmem); +PHP_FUNCTION(domxml_dump_mem); +PHP_FUNCTION(domxml_dump_mem_file); +PHP_FUNCTION(domxml_dump_node); + +#if defined(LIBXML_HTML_ENABLED) +PHP_FUNCTION(domxml_html_dump_mem); +#endif /* Class DocumentType methods */ PHP_FUNCTION(domxml_doctype_name); @@ -89,8 +117,10 @@ PHP_FUNCTION(domxml_node_prefix); PHP_FUNCTION(domxml_node); PHP_FUNCTION(domxml_clone_node); PHP_FUNCTION(domxml_node_unlink_node); +PHP_FUNCTION(domxml_node_replace_node); PHP_FUNCTION(domxml_node_new_child); PHP_FUNCTION(domxml_node_set_content); +PHP_FUNCTION(domxml_node_get_content); PHP_FUNCTION(domxml_node_text_concat); PHP_FUNCTION(domxml_node_set_name); PHP_FUNCTION(domxml_node_name); @@ -135,12 +165,22 @@ PHP_FUNCTION(xpath_init); PHP_FUNCTION(xpath_new_context); PHP_FUNCTION(xpath_eval); PHP_FUNCTION(xpath_eval_expression); +PHP_FUNCTION(xpath_register_ns); #endif #if defined(LIBXML_XPTR_ENABLED) PHP_FUNCTION(xptr_new_context); PHP_FUNCTION(xptr_eval); #endif PHP_FUNCTION(domxml_test); + +/* DOMXSLT functions */ +#if HAVE_DOMXSLT +PHP_FUNCTION(domxml_xslt_stylesheet); +PHP_FUNCTION(domxml_xslt_stylesheet_doc); +PHP_FUNCTION(domxml_xslt_stylesheet_file); +PHP_FUNCTION(domxml_xslt_process); +PHP_FUNCTION(domxml_xslt_version); +#endif #else #define domxml_module_ptr NULL