chregu Fri Nov 28 17:08:17 2003 EDT Added files: /php-src/ext/xsl/tests xslt011.phpt xslt011.xml xslt011.xsl
Modified files: /php-src/ext/xsl php_xsl.c php_xsl.h Log: @- Added possibility to call php functions as XSLT-functions (chregu) - Added possibility to call php functions as XSLT-functions eg: <xsl:value-of select="php:function('date','r')"/> Namespace is http://php.net/functions Index: php-src/ext/xsl/php_xsl.c diff -u php-src/ext/xsl/php_xsl.c:1.9 php-src/ext/xsl/php_xsl.c:1.10 --- php-src/ext/xsl/php_xsl.c:1.9 Wed Nov 19 07:07:59 2003 +++ php-src/ext/xsl/php_xsl.c Fri Nov 28 17:08:13 2003 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_xsl.c,v 1.9 2003/11/19 12:07:59 chregu Exp $ */ +/* $Id: php_xsl.c,v 1.10 2003/11/28 22:08:13 chregu Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -27,6 +27,9 @@ #include "ext/standard/info.h" #include "php_xsl.h" +static void xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs); +static void xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs); + /* If you declare any globals in php_xsl.h uncomment this: ZEND_DECLARE_MODULE_GLOBALS(xsl) */ @@ -136,11 +139,150 @@ #if HAVE_XSL_EXSLT exsltRegisterAll(); #endif + xsltRegisterExtModuleFunction ((const xmlChar *) "functionString", + (const xmlChar *) "http://php.net/xsl", + xsl_ext_function_string_php); + xsltRegisterExtModuleFunction ((const xmlChar *) "function", + (const xmlChar *) "http://php.net/xsl", + xsl_ext_function_object_php); return SUCCESS; } /* }}} */ + +static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) +{ + xsltTransformContextPtr tctxt; + zval **args; + zval *retval; + int result, i, ret; + zend_fcall_info fci; + zval handler; + xmlXPathObjectPtr obj; + char *str; + + TSRMLS_FETCH(); + + tctxt = xsltXPathGetTransformContext(ctxt); + if (tctxt == NULL) { + xsltGenericError(xsltGenericErrorContext, + "xsltExtFunctionTest: failed to get the transformation context\n"); + return; + } + + args = safe_emalloc(sizeof(zval **), nargs - 1, 0); + for (i = 0; i < nargs - 1; i++) { + obj = valuePop(ctxt); + MAKE_STD_ZVAL(args[i]); + switch (obj->type) { + case XPATH_STRING: + ZVAL_STRING(args[i], obj->stringval, 1); + break; + case XPATH_BOOLEAN: + ZVAL_BOOL(args[i], obj->boolval); + break; + case XPATH_NUMBER: + ZVAL_DOUBLE(args[i], obj->floatval); + break; + case XPATH_NODESET: + if (type == 1) { + str = xmlXPathCastToString(obj); + ZVAL_STRING(args[i], str, 1); + xmlFree(str); + } else if (type == 2) { + int j; + dom_object *intern; + array_init(args[i]); + if (obj->nodesetval->nodeNr > 0) { + intern = (dom_object *) php_dom_object_get_data((void *) obj->nodesetval->nodeTab[0]->doc); + for (j = 0; j < obj->nodesetval->nodeNr; j++) { + xmlNodePtr node = obj->nodesetval->nodeTab[j]; + zval *child; + + MAKE_STD_ZVAL(child); + /* not sure, if we need this... it's copied from xpath.c */ + if (node->type == XML_NAMESPACE_DECL) { + xmlNsPtr curns; + xmlNodePtr nsparent; + + nsparent = node->_private; + curns = xmlNewNs(NULL, node->name, NULL); + if (node->children) { + curns->prefix = xmlStrdup((char *) node->children); + } + if (node->children) { + node = xmlNewDocNode(node->doc, NULL, (char *) node->children, node->name); + } else { + node = xmlNewDocNode(node->doc, NULL, "xmlns", node->name); + } + node->type = XML_NAMESPACE_DECL; + node->parent = nsparent; + node->ns = curns; + } + child = php_dom_create_object(node, &ret, NULL, child, intern TSRMLS_CC); + add_next_index_zval(args[i], child); + } + } + } + break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "php:function object type %d is not supported yet", obj->type); + ZVAL_STRING(args[i], "", 0); + } + xmlXPathFreeObject(obj); + } + + fci.size = sizeof(fci); + fci.function_table = EG(function_table); + + obj = valuePop(ctxt); + INIT_PZVAL(&handler); + ZVAL_STRING(&handler, obj->stringval, 1); + xmlXPathFreeObject(obj); + + fci.function_name = &handler; + fci.symbol_table = NULL; + fci.object_pp = NULL; + fci.retval_ptr_ptr = &retval; + fci.param_count = nargs - 1; + fci.params = &args; + fci.no_separation = 0; + /*fci.function_handler_cache = &function_ptr;*/ + + result = zend_call_function(&fci, NULL TSRMLS_CC); + if (result == FAILURE) { + if (Z_TYPE(handler) == IS_STRING) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(&handler)); + } + } else { + if (retval->type == IS_BOOL) { + valuePush(ctxt, xmlXPathNewBoolean(retval->value.lval)); + } else { + convert_to_string_ex(&retval); + valuePush(ctxt, xmlXPathNewString( Z_STRVAL_P(retval))); + } + zval_ptr_dtor(&retval); + } + zval_dtor(&handler); + for (i = 0; i < nargs - 1; i++) { + zval_ptr_dtor(&args[i]); + } + efree(args); +} + +static void +xsl_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs) +{ + xsl_ext_function_php(ctxt, nargs, 1); +} + +static void +xsl_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs) +{ + xsl_ext_function_php(ctxt, nargs, 2); +} + /* {{{ xsl_object_get_data */ zval *xsl_object_get_data(void *obj) { Index: php-src/ext/xsl/php_xsl.h diff -u php-src/ext/xsl/php_xsl.h:1.5 php-src/ext/xsl/php_xsl.h:1.6 --- php-src/ext/xsl/php_xsl.h:1.5 Wed Nov 19 07:07:59 2003 +++ php-src/ext/xsl/php_xsl.h Fri Nov 28 17:08:13 2003 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_xsl.h,v 1.5 2003/11/19 12:07:59 chregu Exp $ */ +/* $Id: php_xsl.h,v 1.6 2003/11/28 22:08:13 chregu Exp $ */ #ifndef PHP_XSL_H #define PHP_XSL_H @@ -46,6 +46,9 @@ #include "../dom/xml_common.h" #include "xsl_fe.h" +#include <libxslt/extensions.h> +#include <libxml/xpathInternals.h> + typedef struct _xsl_object { zend_object std; void *ptr; Index: php-src/ext/xsl/tests/xslt011.phpt +++ php-src/ext/xsl/tests/xslt011.phpt --TEST-- Test 11: php:function Support --SKIPIF-- <?php require_once('skipif.inc'); ?> --FILE-- <?php print "Test 11: php:function Support\n"; $dom = new domDocument(); $dom->load(dirname(__FILE__)."/xslt011.xsl"); $proc = new xsltprocessor; $xsl = $proc->importStylesheet($dom); $xml = new DomDocument(); $xml->load(dirname(__FILE__)."/xslt011.xml"); print $proc->transformToXml($xml); function foobar($id ) { if (is_array($id)) { return $id[0]->value; } else { return $id; } } --EXPECT-- Test 11: php:function Support <?xml version="1.0"?> foobar foobar Index: php-src/ext/xsl/tests/xslt011.xml +++ php-src/ext/xsl/tests/xslt011.xml <doc id="foobar"></doc> Index: php-src/ext/xsl/tests/xslt011.xsl +++ php-src/ext/xsl/tests/xslt011.xsl <?xml version='1.0'?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" xsl:extension-element-prefixes="php" version='1.0'> <xsl:template match="/"> <xsl:value-of select="php:functionString('foobar', /doc/@id)"/> <xsl:text> </xsl:text> <xsl:value-of select="php:function('foobar', /doc/@id)"/> </xsl:template> </xsl:stylesheet> -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php