Project

Profile

Help

Node.JS: Evaluation context and asynchronous processing other than HTTP requests

Added by Gustavo Oga over 3 years ago

Calling Asynchronous functions (Promises) from global object

I have node.js asynchronous code that I would like to call from an XSLT template.

The documentation talks about calling global functions here: https://www.saxonica.com/saxon-js/documentation/index.html#!development/global.

function square(x) { return String(x*x) } 

... <xsl:value-of select="js:square('5')" />...

... the function that I want to call would follow the same pattern, except that it returns a Promise:

function square(x) { return new Promise((resolve) => { ... async work and resolve(result); } } 

... <xsl:value-of select="js:square('5')" />...

It was pointed to me ixsl:schedule-action can be used to perform async work, but as far as I can tell it only supports HTTP requests.

Is there any other way to perform a call to an async function from a XSL?

Using an object other than the global or window object as JavaScript context

[I've split your second question into a separate thread. See https://saxonica.plan.io/boards/5/topics/8084 - MHK]


Replies (3)

Please register to reply

RE: Node.JS: Evaluation context and asynchronous processing other than HTTP requests - Added by Michael Kay over 3 years ago

We don't have this capability at the moment, I'm afraid. It's on our roadmap: see my Balisage 2020 paper for an outline of our thinking on this:

https://www.balisage.net/Proceedings/vol25/html/Kay01/BalisageVol25-Kay01.html

It's a fairly major project so it's going to take a little while.

(I wonder if there's something you can improvise using events in the meantime?)

RE: Node.JS: Evaluation context and asynchronous processing other than HTTP requests - Added by Gustavo Oga over 3 years ago

Sadly it seems ixsl:event is only available on the browser side:

https://www.saxonica.com/saxon-js/documentation/index.html#!ixsl-extension/functions/event

Node.js does have event emitter support, so I'm guessing this could be made available at some point:

https://nodejs.org/api/events.html

For now, it seems I won't be able to call my async code unless I put it through an HTTP request, which is doable albeit a bit wasteful for my purposes.

RE: Node.JS: Evaluation context and asynchronous processing other than HTTP requests - Added by Gustavo Oga over 3 years ago

I decided to go ahead and implement the asynchronous action through an HTTP request, despite the additional overhead involved.

My XSL looks like this:

My source doc is something like:

<topic xmlns:fq="https://eoga.dev/fishq#" xmlns:fx="https://eoga.dev/fishx#" xmlns="https://eoga.dev/fishx#">
  <fq:person name="Emmanuel" />
</topic>

The relevant part of the XSL:

    <xsl:template match="fq:*">
        <query-result>
            <xsl:variable name="query-name" select="xs:string(local-name())" />
            <xsl:variable name="query-params" select="map:merge(@* ! map{local-name(): string()})" />
            <xsl:variable name="query-uri" select="'https://localhost/_query_/' || $query-name" />
            <ixsl:schedule-action document="{$query-uri}">
                <xsl:call-template name="render-query">
                    <xsl:with-param name="query-name" select="$query-uri"/>
                </xsl:call-template>
            </ixsl:schedule-action>
        </query-result>
    </xsl:template>
    <xsl:template name="render-query">
        <xsl:param name="query-name"/>
        <xsl:apply-templates select="doc($query-name)"/>
        {$query-name}
        <ok>DONE.</ok>
    </xsl:template>

The output:

<topic xmlns:fq="https://eoga.dev/fishq#" xmlns:fx="https://eoga.dev/fishx#" xmlns="https://eoga.dev/fishx#">
  <query-result />
</topic>

I can see that Saxon/JS is performing the request. If I introduce an error on the https://localhost/_query_/person, it even throws an exception because of malformed XML. So it is picking up the document. But when it calls the template, nothing happens: not only doc() doesn't have the document yet, but also the rest of the template seems to be ignored. It looks as if the call-template directive is not doing anything.

    (1-3/3)

    Please register to reply