我正在尝试将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版本中是否缺少此功能,或者我做错了什么?
答案 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();
}
}
我原以为使用精确的构造函数就足够了,但似乎没有。