Sunday, November 11, 2018

Retrieving subset of xml using xslt mediator in WSO2 ESB 5.0.0

This article explain a solution to a scenario, where our back end service is not supporting a pagination and responds with a large xml and our client expects an API which need to support pagination.

The flow diagram below summarizes the task we are going to achieve.
Back end service which provides the Students Data

1) Originates a call with the below URL:

http://<host>:<port>/listStudents/

getPaginatedStudentsList?start=0&count=10

2) Call backend service to
retrieve all the students list
3) XSLT mediator do the extraction of
the subset and send back the response.
4) Client receives the paginated response

The API I have created for this sample as below:

<api xmlns="http://ws.apache.org/ns/synapse" name="PaginationAPI" context="/listStudents">
   <resource methods="GET" uri-template="/getPaginatedStudentsList?start={start}&amp;count={count}" protocol="http">
      <inSequence>
         <log level="custom">
            <property name="STATUS" value="PaginationAPI Invoked..."/>
            <property name="start" expression="$ctx:query.param.start"/>
            <property name="count" expression="$ctx:query.param.count"/>
         </log>
         <script language="js">var count = parseInt(mc.getProperty('query.param.count'));                var start = parseInt(mc.getProperty('query.param.start'));        var startIndex = parseInt(start);       var endIndex = parseInt(start) + parseInt(count) + 1;         mc.setProperty('startIndex', startIndex);        mc.setProperty('endIndex', endIndex);</script>
         <call>
            <endpoint>
               <http method="GET" uri-template="http://www.mocky.io/v2/5be818f7300000750058c312"/>
            </endpoint>
         </call>
         <log level="full" description="before xslt transformation"/>
         <xslt key="gov:/pagination-test.xslt">
            <property name="startIndex" expression="$ctx:startIndex"/>
            <property name="endIndex" expression="$ctx:endIndex"/>
         </xslt>
         <respond/>
      </inSequence>
      <outSequence/>
      <faultSequence/>
   </resource>
</api>
                        

The back end service has been created in mocky.io and the sample data response from it will be as below:

<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
 <soapenv:Header/>
 <soapenv:Body>
  <students>
   <school>St.Michael's College, Batticaloa</school>
   <address>Batticaloa, Srilanka</address>
   <student>
    <recno>1</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
   <student>
    <recno>2</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1
   </address>
    <age>27</age>
   </student>
   <student>
    <recno>3</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
   <student>
    <recno>4</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
   <student>
    <recno>5</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
   <student>
    <recno>6</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
   <student>
    <recno>7</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
   <student>
    <recno>8</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
   <student>
    <recno>9</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
   <student>
    <recno>10</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
   <student>
    <recno>11</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
   <student>
    <recno>12</recno>
    <name>NTest1</name>
    <surname>STest1</surname>
    <address>ATest1</address>
    <age>27</age>
   </student>
  </students>
 </soapenv:Body>
</soapenv:Envelope>

Then the XSLT will be as below:

<?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" version="1.0" encoding="UTF-8" indent="yes"/>
 <xsl:param name="startIndex"></xsl:param>
 <xsl:param name="endIndex"></xsl:param>
 <xsl:template match="/">
  <students>
   <xsl:apply-templates select="//students/student[position() > $startIndex and position() &lt; $endIndex]"/>
  </students>
 </xsl:template>
 <xsl:template match="//students/student[position() > $startIndex and position() &lt; $endIndex]">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>

Below are the test results:
1) When calling the API with URL: http://172.17.0.1:8280/listStudents/getPaginatedStudentsList?start=0&count=20
<students>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>1</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>2</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1
   </address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>3</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>4</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>5</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>6</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>7</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>8</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>9</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>10</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>11</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>12</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
</students>

2) When calling the API with URL: http://172.17.0.1:8280/listStudents/getPaginatedStudentsList?start=5&count=3
<students>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>6</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>7</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
    <student xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <recno>8</recno>
        <name>NTest1</name>
        <surname>STest1</surname>
        <address>ATest1</address>
        <age>27</age>
    </student>
</students>

That's it... and hope this helps someone implementing a pagination scenario.

No comments:

Post a Comment