Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Saxon-HE Integrated Extension Functions | how and where?

Tags:

java

saxon

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

I have red:

  • http://www.saxonica.com/html/documentation/extensibility/integratedfunctions/
  • http://www.saxonica.com/html/documentation/extensibility/integratedfunctions/ext-simple-J.html

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.

like image 256
Piotr Dajlido Avatar asked Oct 28 '15 13:10

Piotr Dajlido


1 Answers

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

like image 57
Piotr Dajlido Avatar answered Nov 03 '22 22:11

Piotr Dajlido