Personnalisation de base > Windchill Customization Basics > Managing Customizations > Full Interface Mechanism for XSLT with Saxon
Full Interface Mechanism for XSLT with Saxon
Windchill uses Saxon library for XSLT capabilities using its reflexive interface. In Windchill 12.1.2.0, Saxon library in Windchill is upgraded to Saxon-HE 11.x from Saxon 9.0.x. With this upgrade, the Java based reflexive interface mechanisms for writing extension functions with Saxon will no longer work. Instead, Windchill uses full-interface mechanism provided by Saxon-HE as a replacement for reflexive mechanism.
You don’t have to write extension function definitions for the saxon’s built-in extension functions. For example, the built-in function like Transform can be used out of the box without writing its definition.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
As per definition of ExtensionFunctionDefinition, since Saxon 9.2, each extension functions should implement ExtensionFunctionDefinition. In a case where you have more than one extension function with the same name but different arity, all of their implementation should be done in the same ExtensionFunctionDefinition implementation.
Use of Full Interface Mechanism for Extension Functionality of Saxon
Definition of the new extension function getBundle of the class wt.util.xml.xslt.extn.JavaRBTranslator.java is as below:
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) )
}
}
The getBundle function used in the mergeReport.xsl might have been used as below with reflexive extension mechanism.

<?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))”/>
Below steps show how to change the use of getBundle from extension mechanism to full-interface mechanism.
1. Create a delegate to write extension function definition as in the example below:
package com.ptc.core.saxon.extn;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
public interface ExtensionFunctionDefinitionDelegate {
ExtensionFunctionDefinition[] getExtensionDefinitions();
}
2. Implement the delegate. Refer to the example below which is an implementation to call JavaRBTranslator.getBundle using full interface mechanism.
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. Register the delegate and the service class for the appropriate xsl selectors in service.poperties.xconf file. Use xconfmanager to propagate the changes.

<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. Replace the reflexive extension functions with full interface extensions as below:
<?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. The created function needs to be registered with Saxon. Below example shows the registration and use of the created function.
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);
}
}
}
Est-ce que cela a été utile ?