You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Saxon Processor进行XSLT-2.0 XML转换时遇XPST0017函数未找到错误

迁移至Saxon后XSLT扩展函数找不到的解决方法

问题背景

移除Xalan依赖改用Saxon执行XSLT 2.0格式的XML转HTML操作时,PLMXML_DefaultProcessReport.xsl第22行触发错误:找不到Q{com.teamcenter.rac.cme.cmereport.CMEReportXalanExtension}new()无参函数。核心原因是原XSL使用了Xalan专属的<lxslt:component>扩展机制,Saxon不兼容该语法。

原报错相关代码

XSL文件关键片段

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:plm="http://www.plmxml.org/Schemas/PLMXMLSchema"
xmlns:lxslt="http://www.apache.org/xslt"
xmlns:setfile ="com.teamcenter.rac.cme.cmereport.CMEReportXalanExtension">

<!-- Xalan专属扩展声明 -->
<lxslt:component prefix="setfile" elements="copy" functions="setFile setTcFile getCurrentDir
        getCurrentImanFileName getCurrentImanFileNamePrefix getNiceName">
  <lxslt:script lang="javaclass" src="com.teamcenter.rac.cme.cmereport.CMEReportXalanExtension"/>
</lxslt:component>

<!-- 报错的函数调用 -->
<xsl:param name="outDir" select="setfile:getCurrentDir(setfile:new())"/>

Java转换调用代码

{
        // 1. 实例化TransformerFactory
        javax.xml.transform.TransformerFactory tFactory =(SAXTransformerFactory) SAXTransformerFactory.newInstance();

        XslImportResolver myResolve = new XslImportResolver();
        tFactory.setURIResolver( myResolve );

        // 2. 处理样式表生成Transformer
        javax.xml.transform.Transformer transformer = tFactory.newTransformer
                        (new javax.xml.transform.stream.StreamSource(xslLocation));

        // 注册相关调试输出(原代码保留)
        Registry registry = Registry.getRegistry( this );

        // 3. 执行转换
        transformer.transform( new StreamSource( xmlLocation ),
                new StreamResult( new FileOutputStream( htmlLocation ) ) );
    }

报错信息

Static error near {...e:getCurrentDir(setfile:new...} at char 22 in expression in xsl:param/@select on line 22 column 73 of PLMXML_DefaultProcessReport.xsl:
XPST0017: Cannot find a 0-argument function named Q{com.teamcenter.rac.cme.cmereport.CMEReportXalanExtension}new()

中文翻译:
静态错误,位于PLMXML_DefaultProcessReport.xsl第22行第73列的xsl:param/@select表达式中,字符22附近:
XPST0017:找不到名为Q{com.teamcenter.rac.cme.cmereport.CMEReportXalanExtension}new()的无参函数

解决步骤

1. 替换Xalan扩展声明为Saxon兼容方式

Saxon不支持Xalan的<lxslt:component>扩展语法,需改用Saxon原生支持的Java扩展命名空间。修改XSL的命名空间声明,移除Xalan相关的lxslt命名空间和标签:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:plm="http://www.plmxml.org/Schemas/PLMXMLSchema"
xmlns:setfile="java:com.teamcenter.rac.cme.cmereport.CMEReportXalanExtension">

<!-- 移除原有的<lxslt:component>标签 -->

2. 调整扩展函数调用逻辑

Saxon调用Java实例方法时,需通过类名直接实例化对象(前提是类有public无参构造函数)。修改报错的参数声明:

<xsl:param name="outDir" select="setfile:getCurrentDir(setfile:CMEReportXalanExtension())"/>

如果getCurrentDir可以改为静态方法,可进一步简化为直接调用静态方法,无需实例化:

<xsl:param name="outDir" select="setfile:getCurrentDir()"/>

3. (可选)Java代码中显式注册扩展函数

若直接使用java:前缀的方式不生效,可在Java代码中显式向Saxon注册扩展函数,确保函数能被识别:

// 直接实例化Saxon的TransformerFactory实现
net.sf.saxon.TransformerFactoryImpl tFactory = new net.sf.saxon.TransformerFactoryImpl();

// 注册setfile:new()扩展函数
tFactory.getConfiguration().registerExtensionFunction(new net.sf.saxon.lib.ExtensionFunction() {
    @Override
    public QName getFunctionQName() {
        // 对应XSL中的setfile命名空间和new函数名
        return new QName("com.teamcenter.rac.cme.cmereport.CMEReportXalanExtension", "setfile", "new");
    }

    @Override
    public SequenceType[] getArgumentTypes() {
        return new SequenceType[0]; // 无参数
    }

    @Override
    public SequenceType getResultType() {
        // 返回值为CMEReportXalanExtension对象
        return SequenceType.makeSequenceType(ItemType.OBJECT_TYPE, OccurrenceIndicator.ONE);
    }

    @Override
    public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
        // 创建扩展类实例并返回
        return new ObjectValue<>(new com.teamcenter.rac.cme.cmereport.CMEReportXalanExtension());
    }
});

// 后续设置URIResolver、创建Transformer等代码保持不变
XslImportResolver myResolve = new XslImportResolver();
tFactory.setURIResolver( myResolve );

javax.xml.transform.Transformer transformer = tFactory.newTransformer(new javax.xml.transform.stream.StreamSource(xslLocation));

Registry registry = Registry.getRegistry( this );

transformer.transform( new StreamSource( xmlLocation ),
        new StreamResult( new FileOutputStream( htmlLocation ) ) );

4. 验证扩展类的可访问性

确保com.teamcenter.rac.cme.cmereport.CMEReportXalanExtension类:

  • 存在于Saxon的类路径中
  • 拥有public无参构造函数
  • 被调用的getCurrentDir等方法为public权限

内容的提问来源于stack exchange,提问作者ashish sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 02:18:08