Forums » Saxon-CE help »
Data types of numeric parameters passed to javascript functions
Added by Matt Wallis over 11 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 11 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 11 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 11 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 11 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 11 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?
Please register to reply