Cheat sheet for XSL transformation

I'm really publishing this blog post for myself as a future reference. :)

This .xsl file (aka XSL transformation file) contains perhaps 90% of everything I generally use in my Oracle SOA development projects.

Here is the file in its entirety (I'll break it down further below):

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:ns0="http://revelationtech.com/JobCodes"
                xmlns:socket="http://www.oracle.com/XSL/Transform/java/oracle.tip.adapter.socket.ProtocolTranslator"
                xmlns:oracle-xsl-mapper="http://www.oracle.com/xsl/mapper/schemas"
                xmlns:dvm="http://www.oracle.com/XSL/Transform/java/oracle.tip.dvm.LookupValue"
                xmlns:mhdr="http://www.oracle.com/XSL/Transform/java/oracle.tip.mediator.service.common.functions.MediatorExtnFunction"
                xmlns:oraxsl="http://www.oracle.com/XSL/Transform/java"
                xmlns:oraext="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.ExtFunc"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions"
                exclude-result-prefixes="oracle-xsl-mapper xsi xsd xsl ns0 socket dvm mhdr oraxsl oraext xp20 xref"
                xmlns:plt="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"
                xmlns:tns="http://xmlns.oracle.com/pcbpel/adapter/file/Application/Project/FileRead"
                xmlns:pc="http://xmlns.oracle.com/pcbpel/"
                xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                xmlns:strClass="http://www.oracle.com/XSL/Transform/java/java.lang.String"
                xmlns:jca="http://xmlns.oracle.com/pcbpel/wsdl/jca/">
  <oracle-xsl-mapper:schema>
    <oracle-xsl-mapper:mapSources>
      <oracle-xsl-mapper:source type="WSDL">
        <oracle-xsl-mapper:schema location="../WSDLs/FileRead.wsdl"/>
        <oracle-xsl-mapper:rootElement name="jobcodes" namespace="http://revelationtech.com/JobCodes"/>
      </oracle-xsl-mapper:source>
    </oracle-xsl-mapper:mapSources>
    <oracle-xsl-mapper:mapTargets>
      <oracle-xsl-mapper:target type="WSDL">
        <oracle-xsl-mapper:schema location="../WSDLs/FileRead.wsdl"/>
        <oracle-xsl-mapper:rootElement name="jobcodesconcat" namespace="http://revelationtech.com/TargetInfo"/>
      </oracle-xsl-mapper:target>
    </oracle-xsl-mapper:mapTargets>
  </oracle-xsl-mapper:schema>
  <xsl:template match="/">
    <ns0:targetinfo>
      <xsl:for-each select="/ns0:jobcodes/ns0:jobcode">
        <xsl:variable name="i" select="position()"/>
        <xsl:value-of select="strClass:replaceAll(concat (/targetinfo, '&quot;', /ns0:jobcodes/ns0:jobcode[$i]/ns0:Active, '&quot;;&quot;', /ns0:jobcodes/ns0:jobcode[$i]/ns0:Code, '&quot;;&quot;', /ns0:jobcodes/ns0:jobcode[$i]/ns0:Name, '&quot;&#13;&#10;'), '&amp;', '%26amp;')"/>
      </xsl:for-each>
    </ns0:targetinfo>
  </xsl:template>
</xsl:stylesheet>

I'll go through each of the various areas, but it'll be a bit modified for clarity.

Selecting

This simply copies an element from the source to the target (the target being /ns0:targetinfo).

<ns0:targetinfo>
  <xsl:value-of select="/ns0:jobcodes/ns0:jobcode/ns0:Active"/>
</ns0:targetinfo>

Looping

This loops through the source array, and references the array position jobcode[$i] in each iteration. You would need to create a counter $i.

<ns0:targetinfo>
  <xsl:for-each select="/ns0:jobcodes/ns0:jobcode">
    <xsl:variable name="i" select="position()"/>
    <xsl:value-of select="/ns0:jobcodes/ns0:jobcode[$i]/ns0:Active"/>
  </xsl:for-each>
</ns0:targetinfo>

Using Quotes

This concatenates a double quote in the beginning and end of the source element before copying it to the target element. A double quote is &quot; and a single quote is &apos;.

<ns0:targetinfo>
  <xsl:value-of select="concat('&quot;', /ns0:jobcodes/ns0:jobcode[$i]/ns0:Active, '&quot;')"/>
</ns0:targetinfo>

Replacing & with &amp;

Many target systems don't like the & sign, and require it to be replaced with &amp;. It looks weird here, but do to this you actually replace &amp; with %26amp;.

<ns0:targetinfo>
  <xsl:value-of select="strClass:replaceAll(/ns0:jobcodes/ns0:jobcode[$i]/ns0:Active, '&amp;', '%26amp;')"/>
</ns0:targetinfo>

If using the strClass namespace, it has to be referenced in the stylesheet above as:

xmlns:strClass="http://www.oracle.com/XSL/Transform/java/java.lang.String"

Adding a Line Break

If you want to add a line break after the element, you will need to manually concatenate the characters &#13; and &$10;.

<ns0:targetinfo>
  <xsl:value-of select="concat (/ns0:jobcodes/ns0:jobcode/ns0:Active, '&#13;&#10;')"/>
</ns0:targetinfo>

Concatenating Source Array to a Single Target Element

This loops through all the source elements, and concatenates them all into a single target element that is comma delimited; the target element being /targetinfo.

<ns0:targetinfo>
  <xsl:for-each select="/ns0:jobcodes/ns0:jobcode">
    <xsl:variable name="i" select="position()"/>
    <xsl:value-of select="strClass:replaceAll(concat (/targetinfo, /ns0:jobcodes/ns0:jobcode[$i]/ns0:Active, ',', /ns0:jobcodes/ns0:jobcode[$i]/ns0:Code, ',', /ns0:jobcodes/ns0:jobcode[$i]/ns0:Name)"/>
  </xsl:for-each>
</ns0:targetinfo>