撒克逊人找不到功能:当前组

时间:2014-12-23 13:08:51

标签: xml maven xslt-2.0 saxon xslt-grouping

我正在尝试将Saxon与XSLT样式表一起使用,并使用XSLT2规范中的代码示例(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>

我在我的pom.xml中使用以下内容

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

并且运行它的代码是:

    @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();
        }
    }

这会在输出控制台上抛出错误

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版本中是否缺少此功能,或者我做错了什么?

2 个答案:

答案 0 :(得分:2)

JAXP再次罢工!问题是,你实际上并没有运行Saxon。

执行此操作时:

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

它看起来好像在调用Saxon方法,不是吗?但是在Java中,静态方法不能以这种方式被覆盖(如果可以的话,我会这样做)。您只是在基类上调用newInstance()方法,该方法在类路径中搜索它找到的第一个XSLT处理器。如果要显式调用Saxon,最好通过执行

来避免类路径搜索
factory = new net.sf.saxon.TransformerFactoryImpl();

答案 1 :(得分:1)

我现在发现了一些有用的东西。

    @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));

//用属性方法替换完全限定的类名,似乎有效

        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();
            }
        }

我原以为使用精确的构造函数就足够了,但似乎没有。