2

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?

Community
  • 1
  • 1
Maestro13
  • 3,656
  • 8
  • 42
  • 72
  • It sounds like you want to turn an array of strings (the result of calling `foo.split(";")`) into a node-set, which doesn't make much sense. – Dagg Nabbit Apr 19 '12 at 06:39
  • http://stackoverflow.com/questions/152822/how-to-declare-a-user-defined-function-returning-node-set – erikxiv Apr 19 '12 at 06:43

2 Answers2

2

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>
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
1

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.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • I wish to include it in an MSXML 6.0 XSLT processor. I hope that will allow you to provide a full code sample for the simple script supplied :-). – Maestro13 Apr 19 '12 at 08:35
  • No, sorry, it won't. My knowledge of Microsoft products is very rusty indeed. – Michael Kay Apr 21 '12 at 17:53
  • No problem, Michael, Martin already provided it - thanks again for your hint to him and me as to where to look for the solution. – Maestro13 Apr 21 '12 at 18:16