summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorChristian Stocker <chregu@php.net>2003-11-28 22:08:16 +0000
committerChristian Stocker <chregu@php.net>2003-11-28 22:08:16 +0000
commit3f07e4364cae8499626d5db4a42cb2d4f6aa6af7 (patch)
tree14e4462286f38dc946aea7e4787db74750c1806e /ext
parent29a46b2ff6efe5b57def5ac8b03f391b9283b36e (diff)
downloadphp-git-3f07e4364cae8499626d5db4a42cb2d4f6aa6af7.tar.gz
@- 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
Diffstat (limited to 'ext')
-rw-r--r--ext/xsl/php_xsl.c142
-rw-r--r--ext/xsl/php_xsl.h3
-rw-r--r--ext/xsl/tests/xslt011.phpt29
-rw-r--r--ext/xsl/tests/xslt011.xml1
-rw-r--r--ext/xsl/tests/xslt011.xsl12
5 files changed, 187 insertions, 0 deletions
diff --git a/ext/xsl/php_xsl.c b/ext/xsl/php_xsl.c
index 534ff41cad..1661a5930f 100644
--- a/ext/xsl/php_xsl.c
+++ b/ext/xsl/php_xsl.c
@@ -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 @@ PHP_MINIT_FUNCTION(xsl)
#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)
{
diff --git a/ext/xsl/php_xsl.h b/ext/xsl/php_xsl.h
index f0ce76955e..cdcea90f42 100644
--- a/ext/xsl/php_xsl.h
+++ b/ext/xsl/php_xsl.h
@@ -46,6 +46,9 @@ extern zend_module_entry xsl_module_entry;
#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;
diff --git a/ext/xsl/tests/xslt011.phpt b/ext/xsl/tests/xslt011.phpt
new file mode 100644
index 0000000000..a9b9f5767c
--- /dev/null
+++ b/ext/xsl/tests/xslt011.phpt
@@ -0,0 +1,29 @@
+--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
diff --git a/ext/xsl/tests/xslt011.xml b/ext/xsl/tests/xslt011.xml
new file mode 100644
index 0000000000..134efd02c0
--- /dev/null
+++ b/ext/xsl/tests/xslt011.xml
@@ -0,0 +1 @@
+<doc id="foobar"></doc>
diff --git a/ext/xsl/tests/xslt011.xsl b/ext/xsl/tests/xslt011.xsl
new file mode 100644
index 0000000000..f6da07b266
--- /dev/null
+++ b/ext/xsl/tests/xslt011.xsl
@@ -0,0 +1,12 @@
+<?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>