Project

Profile

Help

Data types of numeric parameters passed to javascript functions

Added by Matt Wallis over 7 years ago

I've just started experimenting with Saxon-CE. I need to do some maths involving trig functions, which I think I'm better off doing in javascript (but would be happily persuaded otherwise!). However, I have not got past the basic hurdle of understanding how parameters are passed into javascript functions from Saxon-CE.

Consider the following:




  
	
	
	
	  
	
	
	  
	
  


and it's corresponding HTML, with inline javascript functions defined:




  
	
	<script type="text/javascript" language="javascript">
	  function f(a, b) { return a + b }
	  function g(a, b) { return Number(a) + Number(b) }
	</script>
  
  
	<script type="text/javascript" language="javascript" src="../javascript/SaxonceDebug/Saxonce.nocache.js"></script>
	<script type="application/xslt+xml" language="xslt2.0" src="main.xsl" data-initial-template="main"></script>
	
a

123

b

56

f(a, b)

g(a, b)

f(a, b) evaluates to 12356 (string concatenation), and g(a, b) performs arithmetic addition due to the casting in javascript. Is it possible to define an xsl:variable so that it will be passed to javascript as a Number? (My attempts to define as="xs:integer" have clearly not done the trick).


Replies (5)

Please register to reply

RE: Data types of numeric parameters passed to javascript functions - Added by Michael Kay over 7 years ago

I can't see any obvious reason why this isn't working with the as="xs:integer". However, a better way might be to try

<xsl:variable name="a" select="number(ixsp:page()//p[@id ='a'])"/>

Let us know if that works.

Looking at the code in IXSLFunction:

public static Object convertToJavaScript(ValueRepresentation val) throws XPathException { int seqLength = 1; if (val == null) { return null; } if (val instanceof SequenceExtent) { seqLength = ((SequenceExtent)val).getLength(); } if (seqLength == 0) { return null; } else if (seqLength == 1) { if (val instanceof EmptySequence) { return null; } else if (val instanceof StringValue) { return ((StringValue)val).getStringValue(); } else if (val instanceof BooleanValue) { return ((BooleanValue)val).getBooleanValue(); } else if (val instanceof NumericValue) { return ((NumericValue)val).getDoubleValue(); } else if (val instanceof HTMLNodeWrapper) { return ((HTMLNodeWrapper)val).getUnderlyingNode(); } else if (val instanceof JSObjectValue) { return ((JSObjectValue)val).getJavaScriptObject(); } }

I'm a bit anxious that there are cases it isn't covering. The explicit conversion to number (i.e. to xs:double) should force it into the "val instanceof NumericValue" path.

I have a suspicion that the test for SequenceExtent should be something like

if (val instanceof SequenceExtent) { seqLength = ((SequenceExtent)val).getLength(); if (seqLength == 1) { val = ((SequenceExtent)val).itemAt(0); }

to ensure that a sequence containing one number is always passed as a number, not as an array of length one.

RE: Data types of numeric parameters passed to javascript functions - Added by Matt Wallis over 7 years ago

Thanks for the quick reply. I tried



before posting my question, with the same results as with as="xs:integer". I have also tried xs:double, with the same results.

As I'm new to this, I thought there might be some basic mistake I had made.

RE: Data types of numeric parameters passed to javascript functions - Added by Michael Kay over 7 years ago

Could you try another experiment for me? Call the function as f(number($a), number($b)). Thanks.

The conversion from XPath to Javascript values isn't easy because of the absence of any static type information. There will always be a few glitches due to the differences between the type systems, but we ought to be able to get the simple cases right.

RE: Data types of numeric parameters passed to javascript functions - Added by Matt Wallis over 7 years ago

No problem:


	
	
	
	  
	

and f still performs string concatenation, producing 12356.

RE: Data types of numeric parameters passed to javascript functions - Added by Philip Fearon over 7 years ago

From a JavaScript function invoked with a number argument from Saxon-CE, the .constructor property of the argument returns: 'function Object() { [native code] }'

As in the following code:

getConstructor = function(arg) {
    return arg.constructor;
}

Should the return type of convertToJavaScriptObject() be JavaScriptObject instead of Object?

    (1-5/5)

    Please register to reply