We have an ongoing project where we are porting over an older C# system that used custom functions to augment the XSLT processing, and we were planning on writing it in Node.js/saxon-js.
It seems from the documentation that event though the higher order functions feature is available to JavaScript SaxonJS, that might not be the case for the Node.js subset of it.
Is there an alternative to that, still in the realm of Node.js / server-side JavaScript runtime?
2
Answers
First of all, in XSLT 3 with XPath 3.1 there is a rich built-in function library https://www.w3.org/TR/xpath-functions-31/, furthermore
xsl:function
since XSLT 2 allows you to implement more functions in XSLT/XPath itself (https://www.w3.org/TR/xslt-30/#stylesheet-functions).As for SaxonJS (tested with the current 2.5 release) and Node.js to call into JavaScript, the following is an example that works for me:
Output e.g.
Documentation https://www.saxonica.com/saxon-js/documentation2/index.html#!development/global and https://www.saxonica.com/saxon-js/documentation2/index.html#!xdm/conversions, although there the
globalThis
use is not mentioned; I believe that is necessary for Node as there, contrary to client-side JavaScript, a globalfunction
orvar
statement does not create a global function or variable.As for processing nodes, I would think it should be save to access the value with e.g.
data()
before passing to JavaScript, as inI can’t tell for sure how the DOM library used by SaxonJS under Node.js and with the (clojure?) compilation exposes the usual browser know/W3C/WHATWG defined DOM properties and methods; you might need to wait until someone from Saxonica answers that separately or you can consider to ask follow-up questions with more specific details.
As simple
textContent
property of an element node seems to work here:Your question is about extension functions, not about higher-order functions.
Yes, you can write extension functions in Javascript to invoke from a Saxon-JS XSLT stylesheet running under Node.js.
Now the question becomes, what exactly are you trying to do, how are you trying to do it, and how is it failing?
As Martin says, if you are moving from Microsoft’s XSLT 1.0 processor the first thing to do is to check whether you really need extension functions at all, because many things that needed extension functions in XSLT 1.0 can be done natively in XSLT 3.0.
If you do need to use extension functions, then it’s a bit more complicated than in the browser because there is no simple "global object" to hang the functions on. Instead it’s probably best to supply an object whose methods you want to call as an explicit stylesheet parameter.
Martin raised some questions about the DOM support in Node.js. SaxonJS has its own DOM implementation, forked some years ago from https://github.com/xmldom/xmldom, and nodes will be passed to your extension functions as Node objects from this library. The public methods of these objects should (if we got it right) be protected from any name-mangling by the Closure compiler. However, if you want to manipulate nodes, writing your functions in XSLT using
xsl:function
is usually a better option than writing them in Javascript.