EXSLT func:function not registered for XSLT filter module

Hi,

I’m trying to use EXSLT’s func:function with nginx’s xslt filter
module. The effect I think I’m seeing is that my functions are
seemingly ignored.

I made a test XSLT stylesheet:

iona% cat xsl/fish.xsl
<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:x="http://xml.elide.org/fish"
     xmlns:func="http://exslt.org/functions"

    extension-element-prefixes="func">

    <func:function name="x:fish">
        <func:result select="123"/>
    </func:function>

    <xsl:output method="text" encoding="utf-8"
        media-type="plain/text"/>

    <xsl:template match="/">
        <xsl:value-of select="x:fish()"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:template>

</xsl:stylesheet>

iona% xsltproc xsl/fish.xsl vhost/blog.libfsm.org/index.xhtml5
123
iona%

I would expect my <xsl:value-of select=“x:fish()”/> there to give the
same result as under xsltproc. But running the same under nginx gives:

xmlXPathCompOpEval: function fish not found
XPath error : Unregistered function
xmlXPathCompiledEval: evaluation failed
runtime error: file /home/kate/svn/www/xsl/fish.xsl line 19 element 

value-of
XPath evaluation returned no result.

Looking at ngx_http_xslt_filter_module.c I see exsltRegisterAll() is
called, which is what should register libexslt’s handler for
func:function and friends:

#if (NGX_HAVE_EXSLT)
    exsltRegisterAll();
#endif

I know NGX_HAVE_EXSLT is defined because other EXSLT functions (such
as things in the date: and str: namespaces) work fine.

I’m using nginx 1.4.1, which is linked to the same libexslt as my
xsltproc.

Any suggestions, please?


Kate

Hello!

On Sat, Jul 13, 2013 at 12:19:51PM +0200, Kate F wrote:

Hi,

I’m trying to use EXSLT’s func:function with nginx’s xslt filter
module. The effect I think I’m seeing is that my functions are
seemingly ignored.

[…]

Looking at ngx_http_xslt_filter_module.c I see exsltRegisterAll() is
called, which is what should register libexslt’s handler for
func:function and friends:

#if (NGX_HAVE_EXSLT)
    exsltRegisterAll();
#endif

I know NGX_HAVE_EXSLT is defined because other EXSLT functions (such
as things in the date: and str: namespaces) work fine.

It looks like exsltRegisterAll() is called too late for EXSLT
Functions extension.

Please try the following patch:

HG changeset patch

User Maxim D. [email protected]

Date 1373909466 -14400

Node ID bc1cf51a5b0a5e8512a8170dc7991f9e966c5533

Parent 8e7db77e5d88b20d113e77b574e676737d67bf0e

Xslt: exsltRegisterAll() moved to preconfiguration.

The exsltRegisterAll() needs to be called before XSLT stylesheets
are compiled, else stylesheet compilation hooks will not work. This
change fixes EXSLT Functions extension.

diff --git a/src/http/modules/ngx_http_xslt_filter_module.c
b/src/http/modules/ngx_http_xslt_filter_module.c
— a/src/http/modules/ngx_http_xslt_filter_module.c
+++ b/src/http/modules/ngx_http_xslt_filter_module.c
@@ -104,6 +104,7 @@ static void *ngx_http_xslt_filter_create
static void *ngx_http_xslt_filter_create_conf(ngx_conf_t *cf);
static char *ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void
*parent,
void *child);
+static ngx_int_t ngx_http_xslt_filter_preconfiguration(ngx_conf_t *cf);
static ngx_int_t ngx_http_xslt_filter_init(ngx_conf_t *cf);
static void ngx_http_xslt_filter_exit(ngx_cycle_t *cycle);

@@ -163,7 +164,7 @@ static ngx_command_t

static ngx_http_module_t ngx_http_xslt_filter_module_ctx = {

  • NULL, /* preconfiguration */
  • ngx_http_xslt_filter_preconfiguration, /* preconfiguration /
    ngx_http_xslt_filter_init, /
    postconfiguration */

    ngx_http_xslt_filter_create_main_conf, /* create main configuration
    */
    @@ -1111,7 +1112,7 @@ ngx_http_xslt_filter_merge_conf(ngx_conf

static ngx_int_t
-ngx_http_xslt_filter_init(ngx_conf_t *cf)
+ngx_http_xslt_filter_preconfiguration(ngx_conf_t *cf)
{
xmlInitParser();

@@ -1119,6 +1120,13 @@ ngx_http_xslt_filter_init(ngx_conf_t
exsltRegisterAll();
#endif

  • return NGX_OK;
    +}

+static ngx_int_t
+ngx_http_xslt_filter_init(ngx_conf_t *cf)
+{
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_xslt_header_filter;


Maxim D.
http://nginx.org/en/donation.html

On 15 July 2013 19:32, Maxim D. [email protected] wrote:

[…]

as things in the date: and str: namespaces) work fine.

Parent 8e7db77e5d88b20d113e77b574e676737d67bf0e

Xslt: exsltRegisterAll() moved to preconfiguration.

The exsltRegisterAll() needs to be called before XSLT stylesheets
are compiled, else stylesheet compilation hooks will not work. This
change fixes EXSLT Functions extension.

Awesome! Good catch.

Thanks for that. Your patch works fine.


Kate

Hello!

On Wed, Jul 17, 2013 at 06:18:03PM +0200, Kate F wrote:

I know NGX_HAVE_EXSLT is defined because other EXSLT functions (such

Node ID bc1cf51a5b0a5e8512a8170dc7991f9e966c5533

Parent 8e7db77e5d88b20d113e77b574e676737d67bf0e

Xslt: exsltRegisterAll() moved to preconfiguration.

The exsltRegisterAll() needs to be called before XSLT stylesheets
are compiled, else stylesheet compilation hooks will not work. This
change fixes EXSLT Functions extension.

Awesome! Good catch.

Thanks for that. Your patch works fine.

Committed, thanks for testing.


Maxim D.
http://nginx.org/en/donation.html