Project

Profile

Help

developing with saxon ce

Added by Jim Fuller over 8 years ago

I am considering writing up a series of articles on using saxon ce and wanted to get some advice on general development

specifically, I am interested in how well saxon ce plays with third party js libs.

as an example, I am using http://raphaeljs.com/ (I thought it would be illustrative, if not ironic, to generate svg using a js lib).

taking its canonical example

// Creates canvas 320 × 200 at 10, 50 var paper = Raphael(10, 50, 320, 200);

// Creates circle at x = 50, y = 40, with radius 10 var circle = paper.circle(50, 40, 10);

which places a circle on a page

it would appear that I am required to first wrap things up in global local functions to get anything useful done e.g.

function addCircle(x,y,radius){ paper.circle(x,y,radius); }

then I would call addCircle ala <xsl:value-of select="js:addCircle(10,10,10)"/>

I am sure you may have better suggestions, so some general dev questions;

  • do you have any worked up examples of working with non trivial 3rd party js libs ?
  • using xsl:value-of seems to invoke things that 'write' to the screen ... but not xsl:copy-of ... wondering what the underlying logic to this e.g. why can't I invoke via xsl:variable as a no op?
  • I am not having joy using things like js variables in ixsl:eval ... its probably misunderstanding of what goes global or not
  • how to define var paper = Raphael(10, 50, 320, 200); to ensure its global ?

ultimately, I am interested in idioms that allow me to stay in 'xml land' when working with 3rd party libs ... thoughts ?

thx in advance


Replies (1)

RE: developing with saxon ce - Added by Philip Fearon over 8 years ago

Jim Fuller wrote:

I am considering writing up a series of articles on using saxon ce and wanted to get some advice on general development

specifically, I am interested in how well saxon ce plays with third party js libs.

This should be a most useful series and we're keen to learn as much as we can on this ourselves.

as an example, I am using http://raphaeljs.com/ (I thought it would be illustrative, if not ironic, to generate svg using a js lib).

taking its canonical example

// Creates canvas 320 × 200 at 10, 50 var paper = Raphael(10, 50, 320, 200);

// Creates circle at x = 50, y = 40, with radius 10 var circle = paper.circle(50, 40, 10);

which places a circle on a page

it would appear that I am required to first wrap things up in global local functions to get anything useful done e.g.

function addCircle(x,y,radius){ paper.circle(x,y,radius); }

then I would call addCircle ala <xsl:value-of select="js:addCircle(10,10,10)"/>

Sometimes it will be useful to wrap several JS calls in a function like the above so you're not continuously switching between XSLT and JS which might affect code readability and debug transparency - however to call a function using Saxon-CE's ixsl:call, the first argument is a reference to the object containing the function so you can use nested ixsl:call or ixsl:get functions like:

ixsl:call(
              ixsl:call(ixsl:window(), ''Raphael', 10, 50, 320, 200),
              'circle', $x, $y, $radius
              )

I am sure you may have better suggestions, so some general dev questions;

Well, there's a suggestion above but I do tend to use your approach to to keep JavaScript separate from XSLT where possible as this helps with editing and debugging.

do you have any worked up examples of working with non trivial 3rd party js libs ?

There is a sample of an XML editor using a pretty huge 3rd party js library, the alpha or beta license for this has probably expired by now, but I'll include the link:

http://publishinggeekly.com/wp-content/uploads/2011/06/sxedit/sxedit.html

using xsl:value-of seems to invoke things that 'write' to the screen ... but not xsl:copy-of ... wondering what the underlying logic to this e.g. why can't I invoke via xsl:variable as a no op?

The side-effect free nature of XSLT and Saxon's optimisation rules cause xsl:variable to be optimised out if the result isn't used - I'm uncertain whether it's desirable to change this at the moment.

I am not having joy using things like js variables in ixsl:eval ... its probably misunderstanding of what goes global or not how to define var paper = Raphael(10, 50, 320, 200); to ensure its global ?

If the above code occurs standalone (not wrapped within a function) within ixsl:eval then paper will always be a global variable, but normally ixsl:eval is better for creating a global JavaScript function that can be called repeatedly from other parts of the XSLT. This is because ixsl:eval injects script into DOM each time it's called and you don't really want to be doing that within a recursive loop.

ultimately, I am interested in idioms that allow me to stay in 'xml land' when working with 3rd party libs ... thoughts ?

Just some ideas - though I think views will differ (and evolve) on the right approach.

  1. XSLT sequences are useful fo interfacing with JavaScript because they convert to JavaScript arrays
  2. XSLT 2.0 hasn't got maps, but by using name/value pairs within XSLT 2.0 sequences, it's possible to build an emulation of a JavaScript object with a collection of named properties (it helps to format the XSLT code to convey this extra meaning, by using a new line for each name/value pair in the sequence). A utility JS function can be created to do the conversion to a real object from such a sequence (which appears as an array)
  3. Use dot separated JavaScript names for the ixsl:get function and the ixsl:set-property instruction instead of nested calls to ixsl:get
  4. Exploit events in XSLT: you can bind templates to any JavaScript object event not just to DOM element events
  5. Minimise the number of arguments in user-defined JavaScript functions (1 or 2)
  6. Exploit the functional nature of JavaScript - functions are objects and can be assigned to variables
    (1-1/1)

    Please register to reply