Showing posts with label XSL. Show all posts
Showing posts with label XSL. Show all posts

Tuesday, November 6, 2012

Looping In XSL

XSL is a functional language and not a programming language !! XSL variables are not actually variables, once set you cannot change their value !! Why is a for loop not working inside XSL !!

I hope many of us have encountered these questions while using XSL. I have come across many scenarios where I had to create a XSL to iterate through a XML and generate some output but looping is tricky inside XSL. Sure you can run a while loop inside BPEL and get your values assigned but that's clumsy.

Below is some sample code snippet which can be extended based on your requirements and should come handy when trying to loop inside XSL.

  <xsl:template match="/">
  <root>
     <xsl:call-template name="loop">
         <xsl:with-param name="i" select="1" /> 
         <xsl:with-param name="count" select="//code to find the counter for loop" /> 
     </xsl:call-template>
  </root>
  </xsl:template>

  <xsl:template name="loop">
     <xsl:param name="i" /> 
     <xsl:param name="count" /> 
     <xsl:if test="$i <= $count">
        //your code here.You can use the predicate [position() = $i] for correct assignments.
           <xsl:call-template name="loop">
           <xsl:with-param name="i" select="$i + 1" /> 
           <xsl:with-param name="count" select="$count" /> 
           </xsl:call-template>
     </xsl:if>
  </xsl:template>
Hope this helps..

Tuesday, February 7, 2012

Using DVMs in SOA 11g

DVM(Domain Value Maps) are static mappings between a source and target system which can be used in transformations. In SOA 10g, DVMs (.xml) could be imported into the ESB Console and during design time accessed via the lookupDVM XPath functions. I would like to cover the usage of DVMs in SOA 11g and how they can be extended/updated at runtime using SOA Composer.

Within Jdeveloper Right Click on your SOA Composite project and create a new DVM table



You can the use this DVM inside your XSL transformation using the lookupDVM function and finally deploy the code.

Modifying the DVM is equally easier. Just login to the SOA Composer (http://hostname:port/soa/composer)


You can edit the DVM after selecting it and once changes are done Save it and the Commit it. It should commit the changes to the MDS repository and make them available at runtime.

Tuesday, December 14, 2010

Custom XSLT Function in SOA 11g

Its been a while since I blogged and has been busy few months. I recently got a requirement to strip all special characters from an input string in XSLT. Tried checking the list of pre-defined XSLT functions in Jdeveloper 11g to see if we had something similar. Though we have few string functions to normalize whitespaces and others which match against regex patterns. But none which replaced/stripped special characters/regex patterns from a string. So decided to write some custom XSLT function which could do this.

First we create the java class which implements the logic

package customxslt;
import java.io.PrintStream;
public class AdditionalStringFunctions
{
  public static String replaceChars(String input, String regex, String replaceWith)
  {
    String output = input.replaceAll(regex, replaceWith);
    return output;
  }
  public static void main(String[] args)
  {
    AdditionalStringFunctions aSF = new AdditionalStringFunctions();
    String input = "(+91)80-55555555";
    System.out.println(replaceChars(input, "[^0-9]", ""));
  }
}

All the above code does is, check for input string and any characters apart from 0-9 is stripped.

Next create a configuration file.Name the file as ext-mapper-xpath-functions-config.xml. Sample file is provided below

<soa-xpath-functions version="11.1.1"
                     xmlns="http://xmlns.oracle.com/soa/config/xpath"                 xmlns:regex="http://www.oracle.com/XSL/Transform/java/customxslt.AdditionalStringFunctions">
   <function name="regex:replaceChars">
    <classname>customxslt.AdditionalStringFunctions</className>
    <return type="string"/>
    <params>
      <param name="input" type="string"/>
      <param name="regex" type="string"/>
      <param name="replaceWith" type="string"/>
    </params>
    <desc/>
    <detail>
      <![CDATA[This function returns the value after stripping special characters.]]>
    </detail>
  </function>
 </soa-xpath-functions>

Create a folder called META-INF under the JDeveloper\mywork\Regex\TestRegex\classes directory and place the configuration file there.

Now create a jar file and make sure the class file and the ext-mapper-xpath-functions-config.xml are included in it.

Next register the JAR file in Jdeveloper designtime
This can be done via "Tools > Preferences… > SOA" add the JAR file and restart JDeveloper.


The newly created extension function will be available in the component palette under user defined functions page. You can make use it from there in your XSL code.


To make this function available at SOA runtime put the jar file under MW_Home/user_projects/domains/domain_name/lib

Restart the server and test your code.

Tuesday, October 26, 2010

XSLT 2.0 Grouping & Sorting in 11g BPEL

I had a requirement recently where I had to split my incoming XML file(read from a database) based on a particular field and send the split sections to another BPEL process for further processing.

Here is how the Input xml looked like


 
  arr1
  ...
  ...
  
  
  arr2
  ...
  ...
  
  
  arr1
  ...
  ...
  
  
  arr2
  ...
  ...
  


Desired Output looks like this.



  
  arr1
  ...
  ...
  
  
  arr1
  ...
  ...
  


  
  arr2
  ...
  ...
  
  
  arr2
  ...
  ...
  



As can be seen above, the idea was to split the Input xml based on arr_id field into different collections and each collection having data for a particular arr_id. Once this is done, all I had to do is run a loop in my BPEL and for each collection send the data to the 2nd BPEL process.

I decided to use XSLT Grouping and Sorting feature to accomplish this task. If we are using XSLT 1.0 there is a particular way to do this using xsl:key which has been explained well in http://www.jenitennison.com/xslt/grouping/muenchian.html . However this can be done easily in XSLT 2.0 using xsl:for-each-group.

Below is the XSL file which does this task for us,

<xsl:stylesheet version="2.0" xmlns:ns1="http://xmlns.oracle.com/pcbpel/adapter/db/Select_Arrid" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
  <ns1:root>
    <xsl:for-each-group select="*/ns1:Select_Arrid" group-by="ns1:Arr_id">
        <xsl:sort select="current-grouping-key()">
        <ns1:select_arrid_collection>
           <xsl:copy-of select="current-group()">
                <xsl:apply-templates/>
          </xsl:copy-of> 
        </ns1:select_arrid_collection>
      </xsl:sort>
    </xsl:for-each-group>
   </ns1:root>
 </xsl:template>
</xsl:stylesheet>

Make sure the version of XSL is 2.0 for using the xsl:for-each-group construct. Now the xsl can be used in any transform activity and will give us the desired output. Hope this helps someone having similar XSLT grouping requirement in BPEL.