Saxon cannot find function: current-group
我正在尝试将Saxon与XSLT样式表一起使用,并使用XSLT2规范(http://www.w3.org/TR/xslt20/#xsl-for-each-group)中的代码示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <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> |
我在pom.xml中使用以下内容
1 2 3 4 5 | <dependency> <groupId>net.sf.saxon</groupId> Saxon-HE</artifactId> <version>9.6.0-3</version> </dependency> |
和运行它的代码是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @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(); } } |
这会在输出控制台上引发错误
1 2 3 | 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 |
我正在使用的Saxon版本中是否缺少此功能,或者我做错了什么?
JAXP再次罢工!问题是,您实际上没有在运行Saxon。
执行此操作时:
1 | factory = net.sf.saxon.TransformerFactoryImpl.newInstance(); |
它看起来好像您正在调用Saxon方法,不是吗?但是在Java中,不能以这种方式覆盖静态方法(如果可以的话,我会...)。您只需在基类上调用newInstance()方法,该方法将在类路径中搜索它发现的第一个XSLT处理器。如果要显式调用Saxon,最好通过执行
避免类路径搜索
1 | factory = new net.sf.saxon.TransformerFactoryImpl(); |
我现在发现了一些可行的方法。
1 2 3 4 5 6 7 | @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)); |
///用属性方法替换完全限定的类名,似乎可行。
1 2 3 | System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl"); TransformerFactory tfactory = TransformerFactory.newInstance(); |
//
1 2 3 4 5 6 7 8 9 10 | 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(); } } |
我曾经认为使用精确的构造函数就足够了,但似乎还不够。