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

Reply via email to