Is there a simple way to have an extension function in XSLT 1.0 written in javascript return a node-set?
I could create a new java class for this, but I would rather just put some code in the script itself.
When this can be done in another scripting language supported by all or most XSLT processors (VB script? Groovy? C#?), then that's OK too of course.
I have the following simple script:
<msxsl:script language="JScript" implements-prefix="custom">
function xml (input) {
var x = input.split(";");
return x.toString();
}
</msxsl:script>
which returns a string, and hence no problem calling the function in Xpath expressions.
What I would like to have, is a node-set result. But when I change my script to
<msxsl:script language="JScript" implements-prefix="custom">
function xml (input) {
var x = input.split(";");
return x;
}
</msxsl:script>
then calling the function gives an error because the array is not automatically converted to a node-set.
I looked at arrays-with-java-xslt-extensions but that's more in the line of creating a new class for this, which I wish to avoid for now.
So which statements should be added to the script in order to transform the array into a node-set, allowing the function call to be used in Xpath expressions?
Here is an example that should work with MSXML 6 as long as run in a mode allowing script in XSLT to implement extension functions.
The stylesheet code is as follows:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:ms="urn:schemas-microsoft-com:xslt"
xmlns:my="http://example.com/my"
exclude-result-prefixes="ms my">
<xsl:output method="html" version="5.0"/>
<ms:script language="JScript" implements-prefix="my">
<![CDATA[
function tokenize (input) {
var doc = new ActiveXObject('Msxml2.DOMDocument.6.0');
var fragment = doc.createDocumentFragment();
var tokens = input.split(';');
for (var i = 0, l = tokens.length; i < l; i++)
{
var item = doc.createElement('item');
item.text = tokens[i];
fragment.appendChild(item);
}
return fragment.selectNodes('item');
}
]]>
</ms:script>
<xsl:template match="/">
<html>
<head>
<title>Example</title>
</head>
<body>
<h1>Example</h1>
<ul>
<xsl:apply-templates select="my:tokenize('Kibology;for;all')"/>
</ul>
</body>
</html>
</xsl:template>
<xsl:template match="item">
<li>
<xsl:value-of select="."/>
</li>
</xsl:template>
</xsl:stylesheet>
If you want nodes returned, you'll have to create the nodes yourself, using DOM interfaces. I suspect (from memory) that if you return a DOM NodeList from your javascript function it will be treated by the calling XPath code as an XPath nodeset - though you'll have to check the spec carefully for details about how duplicate nodes and document order are handled.
Any questions about XSLT java or javascript extensions need to say what product(s) you are talking about, because there are no standards here.