Feature #5558
closed
Allow clients of SaxonJS to supply a map of custom XPath functions with arbitrary names
Fix Committed on JS Branch:
Description
There's an existing mechanism whereby JavaScript functions which are in the global Window scope are automatically made available as XPath functions in a "js:" namespace, but this excludes use cases where it's desirable to add custom implementation functions in some standard namespace, e.g. the EXPath function libraries, XProc's XPath extension functions, etc.
I'd like to see this appear in the API in the same way that params
member of the options
object appears in the evaluate
function; i.e. as an additional functions
member of options
, whose value is a JavaScript object mapping QNames to JavaScript functions.
- Status changed from New to In Progress
- Priority changed from Low to High
- Sprint/Milestone set to SaxonJS 3.0
Coincidentally, I've just started working on this (or something very close to what you describe). The idea, as I'm conceiving it is:
- You write an
xsl:function
declaration that describes the function. Mark this with visibility='abstract'
so that a function body isn't required (and maybe mark it also in some way to indicate that its implementation is expected to be provided at runtime).
- You register the JavaScript functions that implement your abstract functions in the SaxonJS runtime before calling transform or evaluating an XPath expression.
- The runtime manages argument and return types for the called JavaScript function.
I was hoping for the possibility of something usable in pure XPath (i.e. in SaxonJS.XPath.evaluate
). I'm not sure if the approach you're looking at will be applicable in that case?
What I was hoping for (perhaps naively, since I haven't looked at the relevant source code) was to be able to more or less tap into whatever existing framework is currently responsible for raising JavaScript functions into XPath functions, but just to be able to supply the functions explicitly in the form of a JavaScript object mapping function QNames to JavaScript functions, rather than suppl them by exposing them in the global window scope, which inevitably puts some restrictions on the names of the resulting XPath functions, including that they all end up in a "js" namespace.
Accidentally/stupidly posted the above note instead of previewing it. I can't see a way to edit or delete it, so ... sorry for the evident misreading of your note: I do see that xsl:function
doesn't imply the use of XSLT, and it's just about declaration.
I like it; it looks like it will do what I am hoping for. Pre-registering the functions with the runtime is obviously better than passing them to an evaluate
call every time.
I wonder about the need for an explicit declaration (at the XPath level) of the parameters and return type, though? I can see how it would enable the runtime to perform type-coercion when marshaling parameters and results, e.g. to convert a number returned by a JS function into an xs:string or something if that's how the function's been declared. It seems to me, though, that an implementer at the JS level could just return JavaScript objects that have a well-defined mapping anyway; such as arrays, objects, functions, and otherwise you can use SaxonJS.atom
to return particular types from their JS functions. Maybe the convenience of having the runtime do that for you is worth it, though, and maybe there's some other reason to have an explicit declaration, which I'm not seeing?
There is an edit button. It's the little thing on the right hand side across from the "Updated by" header that looks like a pencil in a checkbox. A microscopic pencil in an itty bitty checkbox.
You will need a mechanism to supply a function type signature, if only to establish the arity and deeper to declare types of arguments and return. Without the latter, especially for arguments, you could get any form of argument supplied at runtime with no hope of any form of graceful type-mismatch recovery, unless your function deliberately does its own runtime type-checking, which will probably be expensive…
John Lumley
Sent from my iPad
On 16 Jun 2022, at 01:58, Saxonica Developer Community notifications@plan.io wrote:
We have in fact implemented a mechanism that allows you to supply both the function signature and a Javascript implementation, and we've used this to implement methods such as the EXPath binary library. The problem is that the data for the function signature is supplied in a rather low-level format, and for external use, we need to decide whether (a) to document this as is, or (b) to provide something with better usability.
Norm Tovey-Walsh wrote in #note-4:
There is an edit button. It's the little thing on the right hand side across from the "Updated by" header that looks like a pencil in a checkbox. A microscopic pencil in an itty bitty checkbox.
Thanks! But weirdly I'm still not seeing it; I have a quotation mark entitled "Quote", an ellipsis entitled "Actions" (which shows "Copy Link" if I click it), and a number providing a permalink.
John Lumley wrote in #note-5:
You will need a mechanism to supply a function type signature, if only to establish the arity and deeper to declare types of arguments and return. Without the latter, especially for arguments, you could get any form of argument supplied at runtime with no hope of any form of graceful type-mismatch recovery, unless your function deliberately does its own runtime type-checking, which will probably be expensive…
Yes it'd be nice to have type-checking (and type-coercion) built into the runtime, but BTW in JavaScript a function does have a length
property analogous to XPath's function-arity
function.
This work has come along nicely. There are still a few details to be worked out, but you can provide a map of functions using signatures described with XPath sequence types and call them directly from XPath.evaluate
or from XSLT.
- Status changed from In Progress to Resolved
The work we've done (in SaxonJS 3.0) for calling XSLT functions from JavaScript and JavaScript functions from XSLT addresses this feature, I believe.
Please register to edit this issue
Also available in: Atom
PDF
Tracking page