Saxon cannot find function: current group

I am trying to use Saxon with XSLT stylesheets and use the code examples in the XSLT2 specification ( http://www.w3.org/TR/xslt20/#xsl-for-each-group )

<table xsl:version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <tr>
    <th>Position</th>
    <th>Country</th>
    <th>City List</th>
    <th>Population</th>
  </tr>
  <xsl:for-each-group select="cities/city" group-by="@country">
    <tr>
      <td><xsl:value-of select="position()"/></td>
      <td><xsl:value-of select="@country"/></td>
      <td>
        <xsl:value-of select="current-group()/@name" separator=", "/>
      </td>
      <td><xsl:value-of select="sum(current-group()/@pop)"/></td>
    </tr>
  </xsl:for-each-group>
</table>

      

I am using the following in my pom.xml

<dependency>
  <groupId>net.sf.saxon</groupId>
  <artifactId>Saxon-HE</artifactId>
  <version>9.6.0-3</version>
</dependency>   

      

and the code to run:

    @Test
    public void testSaxonXslt2GroupTest1() throws Exception {

        File xml_file = Fixtures.XSLT2_TEST1_XML;
        File xsl_file = Fixtures.XSLT2_TEST1_XSL;


        TransformerFactory tfactory = net.sf.saxon.TransformerFactoryImpl.newInstance();
        Transformer transformer = tfactory.newTransformer(new StreamSource(xsl_file));
        File saxonDir = new File("target/saxon/");
        saxonDir.mkdirs();
        try {
            transformer.transform(new StreamSource(xml_file),  
                new StreamResult(new FileOutputStream(new File(saxonDir, "test1.xml"))));
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

      

This throws an error on the output console

SystemId Unknown; Line #13; Column #70; Could not find function: current-group
SystemId Unknown; Line #13; Column #70; function token not found.
(Location of error unknown)java.lang.NullPointerException

      

Is this feature missing in the version of Saxon I'm using, or am I doing something wrong?

+3


source to share


2 answers


JAXP Strikes Again! The problem is that you are not actually using the Saxon version.

When you do this:

factory = net.sf.saxon.TransformerFactoryImpl.newInstance();

      



really looks like you are calling a Saxon method, doesn't it? But in Java static methods cannot be overridden this way (if I could ...). You simply call the newInstance () method in the base class, which looks for the path to the first XSLT processor it finds around. If you want to explicitly call Saxon, it is much better to avoid looking up the classpath by doing

factory = new net.sf.saxon.TransformerFactoryImpl();

      

+2


source


Now I have found something that works.

    @Test
    public void testSaxonXslt2GroupTest1() throws Exception {
//      http://stackoverflow.com/questions/9925483/calling-java-from-xsl-saxon  

        File xml_file = Fixtures.XSLT2_TEST1_XML;
        File xsl_file = Fixtures.XSLT2_TEST1_XSL;
        LOG.debug(FileUtils.readFileToString(xsl_file));

      

// replacing the fully qualified class name with the properties approach seems to work

        System.setProperty("javax.xml.transform.TransformerFactory",
                "net.sf.saxon.TransformerFactoryImpl");
        TransformerFactory tfactory = TransformerFactory.newInstance();

      



//

  Transformer transformer = tfactory.newTransformer(new StreamSource(xsl_file));
            File saxonDir = new File("target/saxon/");
            saxonDir.mkdirs();
            try {
                transformer.transform(new StreamSource(xml_file),  
                    new StreamResult(new FileOutputStream(new File(saxonDir, "test1.xml"))));
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }

      

I thought using the exact constructor would be enough, but it doesn't seem to be the case.

+1


source







All Articles