6

Although writing Saxon Integrated Extension Functions are pretty clear to me.

I have red:

I'm having extremely hard time finding information how to actually get them to work.

Q: Where to put files, do I have to complie anything, do I have to edit saxon configuration? Basically what do I have to do to get this working besides registering an extension function with the s9api Processor.

Piotr Dajlido
  • 1,982
  • 15
  • 28
  • Does the sample in http://www.saxonica.com/html/documentation/extensibility/integratedfunctions/ext-simple-J.html not work for you? I pasted that code into a Java application template created with NetBeans where I had added the `saxon9he.jar` as a library, let the IDE fix the import section for the used classes and interfaces (I had to fix one import for `QName` as the selected import was for a different class), let the IDE add a `throws SaxonApiException` to the `main` method and the code compiled and run and adding `System.out.println(result);` outputted the result. – Martin Honnen Oct 28 '15 at 19:19
  • Or do you want to implement your extension functions and use them when running `net.sf.saxon.Transform` from the command line? – Martin Honnen Oct 28 '15 at 19:21
  • **1)** Thank you for fast reply Martin. Meanwhile I had to figure-out such a basic thing as downloading not compiled version of `SaxonHE`, and as you mentioned, I tried to create project with this source code in `Eclipse`. It's there, but honestly I don't know where to start. So my question is more about setting up `Java` environment with `SaxonHE` source code. **2)** I wish to use my extended function in the `xsl template` such as `` – Piotr Dajlido Oct 29 '15 at 08:20
  • 1
    You don't need the source of Saxon to write Java application in Eclipse or another IDE, the `saxon9he.jar` with the binary classes suffices. As for getting started, I think if you know you want to use Eclipse then perhaps tagging your question appropriately and asking for help setting up an application in IDE gets you a better answer. On the other hand I would guess there are tutorials around that explain getting started with your favorite IDE to write an application using an external library. – Martin Honnen Oct 29 '15 at 09:46
  • Allright, even though you didn't provide any concrete example you got me started. I will post answer as soon as I will get this working with `spring`. – Piotr Dajlido Oct 29 '15 at 11:39

1 Answers1

9

TestMain.java - some java file with access to transformation factory

import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import net.sf.saxon.TransformerFactoryImpl;
import net.sf.saxon.s9api.ExtensionFunction;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.jaxp.SaxonTransformerFactory;
import location.to.test.java.file.Test;

public class TestMain {
    public static void main(String[] args) throws IOException, URISyntaxException, TransformerException {

        TransformerFactory factory = TransformerFactory.newInstance();

        // Grab the handle of Transformer factory and cast it to TransformerFactoryImpl
        TransformerFactoryImpl tFactoryImpl = (TransformerFactoryImpl) factory;

        // Get the currently used processor
        net.sf.saxon.Configuration saxonConfig = tFactoryImpl.getConfiguration();
        Processor processor = (Processor) saxonConfig.getProcessor();

        // Here extension happens, test comes from class Test -> Test.java
        ExtensionFunction test = new Test();
        processor.registerExtensionFunction(test);

        Source xslt = new StreamSource(new File("test.xsl"));
        Transformer transformer = factory.newTransformer(xslt);

        Source text = new StreamSource(new File("input.xml"));
        transformer.transform(text, new StreamResult(new File("result.xml")));
    }
}

Test.java - the actual extension function logic

import net.sf.saxon.s9api.ExtensionFunction;
import net.sf.saxon.s9api.ItemType;
import net.sf.saxon.s9api.OccurrenceIndicator;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.SequenceType;
import net.sf.saxon.s9api.XdmAtomicValue;
import net.sf.saxon.s9api.XdmValue;

public class Test implements ExtensionFunction {

    @Override
    public QName getName() {
        return new QName("http://some.namespace.com", "test");
    }

    @Override
    public SequenceType getResultType() {
        return SequenceType.makeSequenceType(ItemType.STRING, OccurrenceIndicator.ONE);
    }

    @Override
    public net.sf.saxon.s9api.SequenceType[] getArgumentTypes() {
        return new SequenceType[] {};
    }

    @Override
    public XdmValue call(XdmValue[] arguments) throws SaxonApiException {
        String result = "Saxon is being extended correctly.";
        return new XdmAtomicValue(result);
    }

}

test.xsl - test xsl. file

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ext="http://some.namespace.com">
    <xsl:output indent="yes"/>

    <xsl:template match="/">
        <root>
                <xsl:value-of select="ext:test()" />
        </root>
     </xsl:template>
</xsl:stylesheet>

result.xml - the result of entire process

<?xml version="1.0" encoding="UTF-8"?>
<root>Saxon is being extended correctly.</root>

Please notice that namespace used in .java and .xsl file must be the same, declared in QName

Piotr Dajlido
  • 1,982
  • 15
  • 28
  • This code gave me following exception : net.sf.saxon.TransformerFactoryImpl cannot be cast to net.sf.saxon.s9api.Processor at Processor processor = (Processor) saxonConfig.getProcessor(); – Rohit sharma Apr 04 '16 at 11:47
  • Can you make sure that your imports are flawless? – Piotr Dajlido Apr 09 '16 at 16:55
  • What should I do if I am using saxon from the command line? I guess I add the class containing the extension function to the classpath. But how to achieve the equivalent of this: ExtensionFunction test = new Test(); processor.registerExtensionFunction(test); – Árpád Magosányi Oct 06 '16 at 15:01
  • Well you should ask a different question with a little bit more data and link it here :) maybe we can set things straight – Piotr Dajlido Oct 07 '16 at 11:19
  • 1
    Your solution did not work for me. Instead of implementing an ExtensionFunction, I had to extend ExtensionFunctionDefinition, that solved the problem. – gyorgyabraham Jul 31 '18 at 13:37
  • something might have changed since 2015 – Piotr Dajlido Aug 24 '18 at 11:28