About Transformations

General

Transformations are typically linked to an endpoint, and will transform the input into a message that will be send. Transformations can be chained, and are optional. (So instead of using NONE you can just not provide 0 transformations.)

Enumerations required for configuration: 0: NONE 1: XSLT 2: DLL (obsolete) 3: XML to JSON 4: JSON to XML

Technically at most 3 transformations should be required to create almost any reasonable result. (TO XML -> XSLT -> TO JSON) However it could be a good idea to chain multiple XSLT transformations. For example the first XSLT could just be the version from the D9A kit, followed by a second transformation that holds customer specific changes. This has 2 big advantages: 1) it is clear what the customizations are; and 2) it allows to upgrade the D9A transformation if a new version is available without having to redo the customizations to it. There is however also a drawback; only data that is still available in the output from the first XSLT can still be used in the 2nd XSLT.

XSLT

The most important transformation is the XSLT because it allows custom logic. Only XSLT version 1.0 is supportd.

The code for this transformation = 1

A simple example of an XSLT would be:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
	<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no" indent="yes" />
	<!-- 
	Created by: 9Altitudes 
	
	History:
	15/03/2023 XXX Initial Version
	
	Notes:
	Used for: demo purpose / documentation
	-->
	<xsl:variable name="smallCase" select="'abcdefghijklmnopqrstuvwxyz'"/>
	<xsl:variable name="upperCase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

	<xsl:template match="/book">
		<output>
			<name>
				<xsl:value-of select="author/firstName"/>
				<xsl:text> </xsl:text>
				<xsl:value-of select="translate(./author/familyName, $smallCase, $upperCase)"/>
			</name>
			<description>Transformed output.</description>
		</output>
	</xsl:template>

</xsl:stylesheet>

This example converted an input to a different format. Note that the transformation can only add fixed "extra" data, but can not invent data. So all the real data should either come from the input, or be encoded in the XSLT itself.

Special Functions

There are a few helper functions available that assist with problems that are difficult to solve with the XSLT 1.0 functions available. List of currently available functions:

In namespace e-platform:helpers/v1

  • Increment() Returns a new number every time it is called. Incrementing the previous number with 1.

  • Increment('<<counter>>') Creates a "counter" with key <<counter>> and returns an incremented value each time it is called.

  • GetCounterValue('<<counter>>') Returns the current value of the counter with name <<counter>>.

To use a special function the namespace must be referenced in an xmlns:xxx="namespace" attribute at the top of the file. See the example below that creates a "scripts" which is then used to call the functions.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:scripts="e-platform:helpers/v1"
  >
  <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no" indent="yes"/>

  <xsl:template match="/">
    <TRANSFORMATION-RESULT>
      <xsl:call-template name="TestCounter"/>
    </TRANSFORMATION-RESULT>
  </xsl:template>

  <xsl:template name="TestCounter">
    <TEST-COUNTER>
      <xsl:choose>
        <xsl:when test="function-available('scripts:Increment')">
          <invoke method="Increment()">
            <result expect="1">
              <xsl:value-of select="scripts:Increment()"/>
            </result>
          </invoke>
          <invoke method="Increment()">
            <result expect="2">
              <xsl:value-of select="scripts:Increment()"/>
            </result>
          </invoke>
          <invoke method="Increment('')">
            <result expect="3">
              <xsl:value-of select="scripts:Increment('')"/>
            </result>
          </invoke>
          <invoke method="GetCounterValue('')">
            <result expect="3">
              <xsl:value-of select="scripts:GetCounterValue('')"/>
            </result>
          </invoke>
          <invoke method="Increment('XX')">
            <result expect="1">
              <xsl:value-of select="scripts:Increment('XX')"/>
            </result>
          </invoke>
          <invoke method="GetCounterValue('XX')">
            <result expect="1">
              <xsl:value-of select="scripts:GetCounterValue('XX')"/>
            </result>
          </invoke>
          <invoke method="GetCounterValue('YY')">
            <result expect="0">
              <xsl:value-of select="scripts:GetCounterValue('YY')"/>
            </result>
          </invoke>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>FAILURE: Script "e-platform:helpers/v1:Increment()" is not available.</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </TEST-COUNTER>
  </xsl:template>
</xsl:stylesheet>

In namespace: e-platform:core-integration/v1

  • HasSagaId Indicates if a saga id is available, and the result of other saga related functions can be used.

  • GetSagaId Returns the saga id related to the current messag.

  • StoreSagaParameter('<<name>>', '<<value>>') Sets the value of a saga parameter. The variable is automatically created if it did not yet exist.

Example

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:=""
  >
  <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no" indent="yes"/>

  <xsl:template match="/">
    <TRANSFORMATION-RESULT>
      <xsl:call-template name="TestSagaVariables"/>
    </TRANSFORMATION-RESULT>
  </xsl:template>

  <xsl:template name="TestSagaVariables">
    <TEST-SAGA-VARIABLES>
      <xsl:variable name="sagavar-value" select="'example'" />
      <xsl:choose>
        <xsl:when test="function-available('core-integration:HasSagaId')">
          <SagaId>
            <xsl:attribute name="hasSagaId">
              <xsl:value-of select=":()"/>
            </xsl:attribute>
            <xsl:value-of select="core-integration:GetSagaId()"/>
          </SagaId>
          <StoredSagaParameter>
            <name>selfcheck-param</name>
            <value>
              <xsl:value-of select="$sagavar-value"/>
            </value>
            <result>
              <xsl:value-of select="core-integration:StoreSagaParameter('selfcheck-param', $sagavar-value)"/>
            </result>
          </StoredSagaParameter>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>FAILURE: Script "e-platform:core-integration/v1:HasSagaId()" is not available.</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </TEST-SAGA-VARIABLES>
  </xsl:template>
</xsl:stylesheet>

To JSON

This transformation can be used if the input message, or the output of the previous stage in the transformation chain is an XML, and it has to be converted to a JSON object.

One special case is to be mentioned, output that should be transformed to a number must be indicated as such by wrapping the number in `TONUMBER(...)` text.

<author>
  <name>Yuval Noah Harari</name>
  <date>10-02-2015</date>
  <books>TONUMBER(10)</books>
  <numberZero>TONUMBER(000.00)</numberZero>
  <numberText>1234.5<numberText>
</author>

To XML

Converts a json object into an XML structure.

Example

{
  "name": "Yuval Noah Harari",
  "date": "10-02-2015",
  "books": 10,
  "numberZero": 0,
  "numberText": "1234.5"
}

Last updated