Skip to Content
Technical Articles
Author's profile photo Morten Wittrock

Peeking under the hood of CPI’s XSLT processor

Updated June 26th, 2019: The entire blog post has been revised to reflect the major upgrade CPI’s XSLT support received in April of 2019.

When it comes to transforming XML, I’m a huge fan of XSLT. There is a fairly steep learning curve to climb, but once you’ve done so, the power and expressiveness of the language is unmatched. Luckily, XSLT is one of the three mapping options offered by SAP Cloud Integration.

In this blog post, I will take a peek under the hood of CPI’s XSLT processor, to see what we can learn about it.

Peeking under the hood

So CPI supports XSLT, which is great, because XSLT – like bow ties – is cool. But which processor is performing the XML transformations behind the scenes? To answer this, we can utilise XSLT’s built-in system-property function to learn more about the underlying processor (it is safe to use the XSLT 3.0 version of the function, since CPI now supports XSLT 3.0).

The function takes a property name as its only input, and returns the value of that property. Per the W3C specification, XSLT 3.0 implementations must support a number of different properties. However, for this blog post I’m going to focus on the following ones:

  • xsl:version (the supported XSLT version)
  • xsl:vendor (the processor’s implementer)
  • xsl:vendor-url (the URL of the implementer’s web site)
  • xsl:product-name (the processor’s product name)
  • xsl:product-version (the version string of the product)

Right, let’s put all of these in an XSLT 3.0 stylesheet and run it through CPI’s processor. First, the stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

	<xsl:variable name="properties" select="(
		'xsl:version', 
		'xsl:vendor', 
		'xsl:vendor-url', 
		'xsl:product-name', 
		'xsl:product-version')"/>

	<xsl:template match="/">
		<system-properties>
			<xsl:for-each select="$properties">
				<xsl:variable name="prop" select="."/>
				<xsl:element name="{substring-after($prop, ':')}">
					<xsl:value-of select="system-property($prop)"/>
				</xsl:element>
			</xsl:for-each>
		</system-properties>
	</xsl:template>

</xsl:stylesheet>

Executing this stylesheet in CPI, I get the following output:

<?xml version="1.0" encoding="UTF-8"?>
<system-properties>
	<version>3.0</version>
	<vendor>Saxonica</vendor>
	<vendor-url>http://www.saxonica.com/</vendor-url>
	<product-name>SAXON</product-name>
	<product-version>EE 9.8.0.12</product-version>
</system-properties>

This tells us that the XSLT 3.0 processor in CPI is Saxon-EE by Saxonica, the commercial version of the open source Saxon processor. Specifically, CPI runs version 9.8.0.12 at the time of writing.

Java extensions

Prior to the XSLT processor upgrade in April, CPI used Saxon-HE, the open source version of Saxon. One important area, in which the two products differ, is Java extensions, i.e. your ability to execute Java code from within your XSLT stylesheet.

Here’s an example of the so-called reflexive extension functions, where the static pow method of the java.lang.Math class is called:

<xsl:value-of select="math:pow(2,8)" xmlns:math="java:java.lang.Math"/>

Reflexive extension functions are not supported in Saxon-HE, however, and that explains why they weren’t available in CPI, until the XSLT processor received an upgrade.

However, please be aware that calling your own classes from XSLT is not supported and will not work.

Assigned Tags

      12 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Hemachandan A S
      Hemachandan A S

      Hi Morten,

      Useful blog and currently working to get external parameters in xslt mapping with below code but its not working so any suggestions?

      <xsl:param name="external_location" select="getProperties(Job_Location)" />

       

      Thanks,

      Chandan

      Author's profile photo Morten Wittrock
      Morten Wittrock
      Blog Post Author

      Hi Chandan

      Disregard my comment, and instead see Sriprasad's comment below.

      Regards,

      Morten

      Author's profile photo Sriprasad S Bhat
      Sriprasad S Bhat

      Hello Morten,

      Its possible to set and get exchange properties inside XSLT  .

      How to get:

      https://answers.sap.com/questions/341836/hci-xslt-get-property-value.html?childToView=340091#answer-340091

      How to set:

      <?xml version="1.0" encoding="UTF-8"?>
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
          xmlns:hci="http://sap.com/it/" exclude-result-prefixes="hci">
      
      	<xsl:param name="exchange"/>
      	<xsl:param name="Param1"/>
      	<xsl:param name="Param3"/>
      
      	<xsl:output method="xml" encoding="UTF-8" indent="no" />
      
      	<xsl:template match="/">
      		
      		<xsl:value-of select="hci:setProperty($exchange, 'Param2', $Param1)"/>
      		<xsl:value-of select="hci:setProperty($exchange, 'Param3', '222222')"/>
      		<xsl:value-of select="hci:setHeader($exchange, 'Param1', '1234567890')"/>
      
      		<Test1/>
      
      	</xsl:template>
      
      </xsl:stylesheet>

      Regards,

      Sriprasad Shivaram Bhat

      Author's profile photo Morten Wittrock
      Morten Wittrock
      Blog Post Author

      Hi Sriprasad

      That's pretty cool - thanks for commenting! Is that hci: function namespace documented?

      Regards,

      Morten

      Author's profile photo Sophie Kraut
      Sophie Kraut

      Hi Morton, wanted to know if CPI supports XSLT 2.0 and didn' t find the info in the official CPI help,  found then your blog 🙂 . In the tenant i use (2.43.11) it is exactly as in your example. thanks for sharing, best regards, Sophie.

      Author's profile photo Morten Wittrock
      Morten Wittrock
      Blog Post Author

      Hi Sophie

      Thank you for your comment. I’m glad you found it useful!

      Regards,

      Morten

       

      Author's profile photo Tim Wernick
      Tim Wernick

      Hi Morten,

      thanks for this fine blog post. As the SaxonEE is integrated into CPI I wonder if it would be possible to use it as a XSL processor from with a java class called from groovy. As it should be on the classpath I thought this would be possible. However it appears I still receive only the standard XSL 1.0 implementation when using the TransformerFactory.newInstance().newTransformer.

      Do you have any hints on how to get access to the Saxon implementation?

      kind regards

       

      Tim

      Author's profile photo Morten Wittrock
      Morten Wittrock
      Blog Post Author

      Hi Tim

      Thank you for the kind words.

      You can instantiate the Saxon TransformerFactory explicitly like this:

      TransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl()

      I just tried this from a Groovy script in CPI, and it works.

      Regards,

      Morten

      Author's profile photo Tim Wernick
      Tim Wernick

      Hi Morten,

      I solved it now this way:

      TransformerFactory.newInstance("com.saxonica.config.EnterpriseTransformerFactory", null);

      Thanks for helping! Tried to use a file in the META-INF/services to point to the other factory but somehow it didn't work so I switched to the above code.

      And yes I am aware that the code will break in case SAP decides to use a different XSLT processor. Let's hope SAP sticks with SaxonEE 😉

       

      kind regards

       

      Tim

      Author's profile photo Morten Wittrock
      Morten Wittrock
      Blog Post Author

      Ah, right - it's a different class for the EE version, but the principle is the same. Glad you got it working.

      Regards,

      Morten

      Author's profile photo Daniel Graversen
      Daniel Graversen

      Hi Tim,
      We tried on Cloud Foundry/Integration Suite. It seems like running XSLT with Java extensions is no longer possible.

      Such a shame.

      Author's profile photo Morten Wittrock
      Morten Wittrock
      Blog Post Author

      Addendum: This ties your code to Saxon, obviously. So if at some point in the future, CPI starts using another XSLT processor, your code will break. But if the code specifically requires Saxon, then there's not much to do about it anyway.

      Regards,

      Morten