撒克逊找不到函数:current-group
Posted
技术标签:
【中文标题】撒克逊找不到函数:current-group【英文标题】:Saxon cannot find function: current-group 【发布时间】:2015-02-21 15:16:59 【问题描述】:我正在尝试将 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 版本中是否缺少此功能,还是我做错了什么?
【问题讨论】:
我不认为这会造成麻烦,但你为什么指定version="1.0"
?
我认为这是一个转录错误,应该是 2.0。我会检查我的实际代码
我 am 使用 xsl:version="2.0" 在本地运行它
我正在尝试重现这一点,但由于 XSLT 具有 <xsl:value-of select="current-group()/@name" separator=",">
,因此该示例甚至不是格式正确的。当我将代码更正为<xsl:value-of select="current-group()/@name" separator=","/>
时,Saxon 会输出一个结果,至少从命令行运行它。
感谢您的耐心等待。我的代码具有良好的 XML/XSL 格式。我会重新粘贴...
【参考方案1】:
我现在发现了一些有用的东西。
@Test
public void testSaxonXslt2GroupTest1() throws Exception
// http://***.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();
我以为使用精确的构造函数就足够了,但似乎不是。
【讨论】:
我认为您可以直接使用import net.sf.saxon.TransformerFactoryImpl;
执行TransformerFactory tFactory = new TransformerFactoryImpl();
,或者您确实需要设置系统属性。 newInstance
方法是继承的,在 saxonica.com/html/documentation/javadoc/net/sf/saxon/… 中没有覆盖它。
谢谢 - 这似乎可以解释它 - 也许它应该被覆盖或以某种方式被困
如果您认为应该在 Saxon 中修复该问题,您可以向 Saxonica 报告错误或通知 @MichaelKay。【参考方案2】:
JAXP 再次来袭!问题是,您实际上并没有在运行 Saxon。
当你这样做时:
factory = net.sf.saxon.TransformerFactoryImpl.newInstance();
看起来你确实在调用 Saxon 方法,不是吗?但是在 Java 中,不能以这种方式覆盖静态方法(如果可以的话,我会......)。您只是在基类上调用 newInstance() 方法,该方法在类路径中搜索它发现的第一个 XSLT 处理器。如果您想显式调用 Saxon,最好通过这样做来避免类路径搜索
factory = new net.sf.saxon.TransformerFactoryImpl();
【讨论】:
谢谢。现在一切都说得通了。存在不止一种方法可以做到这一点的危险,因此我最终从已知示例中剪切和粘贴并且使事情变得混乱。希望这个例子能帮助其他人做对以上是关于撒克逊找不到函数:current-group的主要内容,如果未能解决你的问题,请参考以下文章
找不到MessageBodyWriter,从fatjar运行时出错