基本自定义 > Windchill 自定义基础 > 管理自定义 > 采用 Saxon 的 XSLT 的完整接口机制
采用 Saxon 的 XSLT 的完整接口机制
Windchill 通过其自反接口将 Saxon 库用于 XSLT 功能。在 Windchill 12.1.2.0 中,Saxon 库从 Saxon 9.0.x 升级到 Saxon-HE 11.x。完成此升级后,用于通过 Saxon 编写扩展函数的 Java 自反接口机制将不再有效。Windchill 改用由 Saxon-HE 提供的完整接口机制,以此作为自反扩展函数的替代方案。
不必为 Saxon 的内置扩展函数编写扩展函数定义。例如,可预设使用内置函数 (如 Transform),而无需编写其定义。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
根据 ExtensionFunctionDefinition 定义,从 Saxon 9.2 开始,每个扩展函数都应实现 ExtensionFunctionDefinition。如果存在多个名称相同但 arity 不同的扩展函数,则应在相同 ExtensionFunctionDefinition 实施中完成其所有实施。
完整接口机制用于 Saxon Extension Functionality
getBundle 的新扩展函数 wt.util.xml.xslt.extn.JavaRBTranslator.java 的定义如下:
package wt.util.xml.xslt.extn;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/** This class serves as an XSLT extension function implementation.*/
public class JavaRBTranslator
{
/** Construct a resource bundle given its name and locale name*/
public static ResourceBundle getBundle( String bundleName, String localeName )
{
//your implementation
return ( ResourceBundle.getBundle( bundleName, locale) )
}
}
mergeReport.xsl 中使用的 getBundle 函数可能已经按如下方式与自反扩展机制配合使用。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:jrb="wt.util.xml.xslt.extn.JavaRBTranslator">
<xsl:varialble name=”jrb” select=”jrb:getBundle(string($javaResourceBundle), string($locale))”/>
以下步骤显示了如何将 getBundle 的使用从扩展机制更改为完整接口机制。
1. 创建一个委派以写入扩展函数定义,如下面的示例所示:
package com.ptc.core.saxon.extn;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
public interface ExtensionFunctionDefinitionDelegate {
ExtensionFunctionDefinition[] getExtensionDefinitions();
}
2. 实施该委派。请参阅以下示例,该实施使用完整接口机制调用 JavaRBTranslator.getBundle
public class ExtensionFunctionResourceBundle extends ExtensionFunctionDefinition{
@Override
public StructuredQName getFunctionQName() {
return new StructuredQName("eg6", "http://example.com/saxon-extension6", "getBundle");
}

@Override
public SequenceType[] getArgumentTypes() {
return new SequenceType[]{SequenceType.SINGLE_STRING, SequenceType.SINGLE_STRING};
}

@Override
public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
return SequenceType.ANY_SEQUENCE;
}

@Override
public ExtensionFunctionCall makeCallExpression() {
return new ExtensionFunctionCall() {
@Override
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
ResourceBundle resourceBundle=null;
String bundleName = arguments[0].head().getStringValue();
String localeName = arguments[1].head().getStringValue();
resourceBundle = JavaRBTranslator.getBundle(bundleName, localeName);

return new ObjectValue(resourceBundle);
}
};
}
}
package com.ptc.windchill.saxon.extn;
import com.ptc.core.saxon.extn.ExtensionFunctionDefinitionDelegate;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
public class ExtensionFunctionDefChangeMonitorImpl implements ExtensionFunctionDefinitionDelegate{
@Override
public ExtensionFunctionDefinition[] getExtensionDefinitions() {
ExtensionFunctionDefinition[] defs = new ExtensionFunctionDefinition[] {
new ExtensionFunctionResourceBundle();
new ExtensionFunctionURIGenerator();
};
return defs;
}
}
3. service.poperties.xconf 文件中为相应的 xsl 选择器注册委派类和服务类。使用 xconfmanager 传播变更。

<Service context="default" name="com.ptc.core.saxon.extn.ExtensionFunctionDefinitionDelegate"> <!-- Delegate-->
<Option cardinality="singleton" requestor="java.lang.Object" serviceClass="com.ptc.windchill.saxon.extn.ExtensionFunctionDefChangeMonitorImpl" selector="changeMonitorReport.xsl" />
<!—Add below entry if required for other ExtensionFunctionDelagate Implementations -->
<Option cardinality="singleton" requestor="java.lang.Object" serviceClass="com.ptc.windchill.saxon.extn.ExtensionFunctionDefChangeMonitor2Impl" selector="changeMonitorReport2.xsl" />
</Service>
4. 以完整接口扩展替代自反扩展函数,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:jrb=http://example.com/saxon-jrb>
5. 所创建的函数需要在 Saxon 中进行注册。下面的示例显示了已创建函数的注册和使用。
XMLSource xslSource = //your xsl file
TransformerFactory transformerFactory = factory.getFactories().getTransformerFactory();
//If the Base URI contains xsl file, then need to register extension definitions only if xsl is available.
if(xslSource.getBaseURI() != null && !xslSource.getBaseURI().equalsIgnoreCase("")) {
TransformerFactoryImpl tFactoryImpl = (TransformerFactoryImpl) transformerFactory;
net.sf.saxon.Configuration saxonConfig = tFactoryImpl.getConfiguration();
//Get the xsl filename
String xslName = new File(xslSource.getBaseURI()).getName();
//Get all extension definitions from the delegate which is registered in the service.properties.xconf file.
ExtensionFunctionDefinitionDelegate extensionDelegate = (ExtensionFunctionDefinitionDelegate)DefaultServiceProvider.getService(ExtensionFunctionDefinitionDelegate.class,xslName);
//Register extension functions
if(null != extensionDelegate)
{
ExtensionFunctionDefinition[] defs = extensionDelegate.getExtensionDefinitions();
for(ExtensionFunctionDefinition def : defs) {
saxonConfig.registerExtensionFunction(def);
}
}
}
这对您有帮助吗?