December 16, 2016

Useful XPath

Join Element Text

Input :
<employees>
    <employee>
        <empId>123</empId>
    </employee>
    <employee>
        <empId>456</empId>
    </employee>
</employees>

XPath : string-join(//empId, ',')

Output :
123,456

Distinct Values in XPath 1.0
Distinct function is not available in XPath 2.0. Therefore in XPath 1.0 you have to use the following.

Input :
<students>
<student>
<studentId>100</studentId>
<subject>Maths</subject>
</student>
<student>
<studentId>102</studentId>
<subject>Science</subject>
</student>
<student>
<studentId>101</studentId>
<subject>English</subject>
</student>
<student>
<studentId>100</studentId>
<subject>English</subject>
</student>
<student>
<studentId>100</studentId>
<subject>Science</subject>
</student>
</students>

XPath : //student/studentId[not(.=preceding::*)]

Output :
<result>
   <studentId>100</studentId>
   <studentId>102</studentId>
   <studentId>101</studentId>
</result>

December 2, 2016

XSLT Tips and Tricks

Remove CDATA section from a XML

Input XML
<request><![CDATA[ 
   <user>
     <firstname>Maheeka</firstname>
     <lastname>Jayasuriya</lastname>
   </user>]]>
</request>

XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output indent="yes"/>
   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
   <xsl:template match="*:request/text()">
      <xsl:value-of disable-output-escaping="yes" select="."/>
   </xsl:template>
</xsl:stylesheet>

Transformed XML
<request> 
   <user>
      <firstname>Maheeka</firstname>
      <lastname>Jayasuriya</lastname>
   </user>
</request>

Extract Element Names to Element Values

Input XML
<user>
   <FirstName>Maheeka</FirstName>
   <LastName>Jayasuriya</LastName>
   <Age>26</Age>
</user>

XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="//user">
      <user>
         <xsl:for-each select="*">
             <xsl:value-of select="local-name()"/> = <xsl:value-of select="."/>,  
         </xsl:for-each>
      </user>
   </xsl:template>
</xsl:stylesheet>

Transformed XML
<user>FirstName = Maheeka,  
LastName = Jayasuriya,  
Age = 26,  
</user>

Group Payload By a Distinct Value

Input XML
<students>
    <student>
        <studentId>100</studentId>
        <subject>Maths</subject>
    </student>
    <student>
        <studentId>102</studentId>
        <subject>Science</subject>
    </student>
    <student>
        <studentId>101</studentId>
        <subject>English</subject>
    </student>
    <student>
        <studentId>100</studentId>
        <subject>English</subject>
    </student>
    <student>
        <studentId>100</studentId>
        <subject>Science</subject>
    </student>
</students>

XSLT
<xsl:stylesheet version="1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <students>
            <xsl:for-each select="//student/studentId[not(.=preceding::*)]">
                <xsl:variable name="studentId" select="."/>
                <student>
                    <studentId>
                        <xsl:value-of select="$studentId"/>
                    </studentId>
                    <xsl:for-each select="//student[studentId=$studentId]/subject">
                        <subject>
                            <xsl:value-of select="."/>
                        </subject>
                    </xsl:for-each>
                </student>
            </xsl:for-each>
        </students>
    </xsl:template>
</xsl:stylesheet>

Transformed XML
<students xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <student>
        <studentId>100</studentId>
        <subject>Maths</subject>
        <subject>English</subject>
        <subject>Science</subject>
    </student>
    <student>
        <studentId>102</studentId>
        <subject>Science</subject>
    </student>
    <student>
        <studentId>101</studentId>
        <subject>English</subject>
    </student>
</students>

November 24, 2016

Parasoft Virtualizer Tips for Generating Dynamic Responses

This post explains how to create dynamic responses when creating Virtual Assets in Parasoft Virtualizer. The dynamic responses may be created depending on the request payload and headers. 

We will work on three cases of dynamic responses here.
  1. Dynamic response from request payload
  2. Dynamic response from request payload with CDATA
  3. Dynamic response from request headers

Getting Started

Let us start by first creating a new Virtual Asset 'Empty' project


Right click on Responder Suite and Add Responder and select JSON Message Responder or Plain XML Message Responder as required. For the purpose of this post, I am selecting Plain XML Message Responder.

In this post we will be providing a firstname and lastname and reply with a email address constructed as "<firstname>.<lastname>@company.com"

1. Dynamic Response from Request Payload

This is the most simple form of dynamic response. We extract data from the request to payload to construct the response. 

Request : 
<request>
<user>
<firstname>Maheeka</firstname>
<lastname>Jayasuriya</lastname>
    </user>
</request>

Expected Response : 
<user>
    <email>Maheeka.Jayasuriya@maheeka.me</email>
</user>

In the created new Responder, go to Options tab and copy the request to the Request Template as below in the Literal view. 


Now go to the Response tab and copy the expected response in the Literal view.

If you now switch to the Form XML response, you are able to see the response and its values of the elements as below.


In order to get the 'firstname' and 'lastname' from the request, we need to extract the data by using a XML Data Bank

For this, right click on the Responder > Add Output.
Select Incoming Request > Payload > XML Data Bank
Now you should be able to see the request we configured earlier on the left view. Select 'firstname' and click on 'Extract Element'. This will add a Data Source Column with the value extracted from the selected 'firstname' element's XPath.

Select the added Data Source and click 'Modify'. Click on 'Evaluate XPath' and you should be able to see the extracted value from the request. Here, 'firstname' element that was selected resolves to 'Maheeka'


However, since we need to create the email from 'firstname' and 'lastname', let's modify this entry as below. You can add any XPath using XPath 1.0 functions for this. I am modifying the XPath as 'concat(/request/user[1]/firstname[1]/text(), '.' , /request/user[1]/lastname[1]/text(), '@maheeka.me')' which resolves to 'Maheeka.Jayasuriya@maheeka.me'
Also, we need to modify the Data Source Column name to email.
Now I need to create the response to get the email from the Data Source Column that we just created.

Go back to the Responder's Response tab and click on email element and select 'Parameterized' for Value. This will list down the columns that we created and you can select 'email' from here. 
Now you need to add this Virtual Asset to a local server or a remote server and invoke the service with a POST request as below, 

2. Dynamic Response from Request Payload with CDATA

Here we get a part of the response in a CDATA section. We need to extract data from this CDATA section to construct the response. 

Request : 
<request>
<![CDATA[ 
<user>
<firstname>Maheeka</firstname>
<lastname>Jayasuriya</lastname>
</user>
]]>
</request>

Expected Response : 
<user>
    <email>Maheeka.Jayasuriya@maheeka.me</email>
</user>

Most of the steps are similar to above. However, in addition, we have a step to extract data from the CDATA section. In order to do that, we are adding an XSL transformation before we extract data to the XML Data Bank.

Right click on the Responder > Add Output  > Payload and Select XSLT.

Following XSLT can be used to extract the CDATA from the XML payload.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*:request/text()">
<xsl:value-of disable-output-escaping="yes" select="."/>
</xsl:template>
</xsl:stylesheet>

If you test out this XSLT with the above payload, you will see that this transforms the request to below. You can easily test this using an online tool like http://www.freeformatter.com/xsl-transformer.html (there are many other tools as well).

<request>
<user>
<firstname>Maheeka</firstname>
<lastname>Jayasuriya</lastname>
</user>
</request>

Now, this is similar to the payload earlier in the 1st scenario. Therefore, we can do the same steps to create an XML Data Bank to extract the first name and last name and set the email Data Source column and set it to the response.

Right click on the Incoming Request -> XSLT and Add Output > Transformed Source > XML Data Bank. Add the converted payload from XSLT to the left panel and extract from their XPath to create email column as below.



Now you need to add the email column as the parameter for email element in the response payload. Redeploy the virtual asset and invoke the service similar to, the earlier scenario. Following is the response from invoking the service using Postman.

3. Dynamic response from request headers

Sometimes, the request data are coming as headers or as URL parameters. At this point, we need to extract the data from the header to get the 'firstname' and 'lastname' to construct email.

Request : 
GET http://localhost:9080/DynamicResponderServer?firstname=Maheeka&lastname=Jayasuriya

Expected Response : 
<user>
    <email>Maheeka.Jayasuriya@maheeka.me</email>
</user>

First, few steps are similar to above, up until creating a Responder. Here we need to extract the query parameters from the raw request. Therefore, we will be using a Text Data Bank for this.

Right Click on the Responder and Add Output > Incoming Request > Transport Header > Text Data Bank.


Go to Postman and add query parameters 'firstname' and 'lastname' as below.
If you click on 'Code' link on the bottom right corner as in above diagram, you are able to copy the raw request from Postman as below.
Following is the raw request for this sample.

GET /DynamicResponderServer?firstname=Maheeka&amp;lastname=Jayasuriya HTTP/1.1
Host: localhost:9080
Content-Type: application/xml
Cache-Control: no-cache
Postman-Token: 9cd3e89e-74d1-8b78-ac5e-c7ccdd4b7e0e

Now go back to Virtualizer and add this raw request on the Text Content panel of the Text Data Bank.
By selecting any text you need from the raw request, you can add a Data Source Column.

First, let's try to get the full URL of the request. Select the URL from the first line in the request as below, and click on Add.



Create an additional element in the response payload (refer above scenario steps on constructing the response format) called url and select the URL Data Source column here for the value as below.

Now deploy the Virtual Asset and invoke via Postman.
If you take a look at the URL that is available in the response, you will notice that the query parameters are not in the order we sent in the request.

In the request we sent as :
/DynamicResponderServer?firstname=Maheeka&lastname=Jayasuriya

In Virtualizer however, the request have come as :
/DynamicResponderServer?lastname=Jayasuriya&amp;firstname=Maheeka

This is something I had to figure out the hard way :). I am not sure why this happens in Virtualizer. However, it is best to first try to get the value of the URL like this and then do the 'firstname' and 'lastname' extractions.

Now back to the Text Data Bank view. We need to modify the URL in the raw request with the one we got by invoking via Postman.

Now Select the 'Jayasuriya' part and Click on Add > OK

The parameters are listed in the table underneath the text panel. If you click on Modify after selecting 'lastname', you will see the following Dialog. Here Virtualizer has extracted few characters before and after the text that we selected, in order to uniquely identify the value. 

'
We can make it further unique by adding the complete query parameter name in the 'Left Hand text as below. Also, we need to select URL Decoded to allow special characters to be decoded when extracting. For example & becomes &amp; when decoded. Since query parameters will have & sign, we need to select this option.

We need to do the same with 'firstname' as in the Dialog below.


Now let's go back to the response view and remove the previously added URL element. Now if you select on the email element, we can now add the email address value as below. We do not have a column as email this time. Instead, we are constructing the email here itself in the Fixed option as "${firstname}.${lastname}@maheeka.me". ${column_name} is the notation used to extract values from a data column.


Another way of constructing the email here is to use a JavaScript code. If you want to use a JavaScrip function, instead of Fixed or Parameterized, select Script option.
Click on 'Edit Script'. This will bring up the below Dialog, where you can write a JavaScript function to do the same construction of email address. If there are no errors in the JavaScript source, if you click on Evaluate there should be no errors and the Methods drop down should be populated. Select the relevant method (if you have multiple) that will be executed to get the value. 

Following is the JavaScript function : 

function getEmailAddress(context) {
   return context.getValue("Text Data Bank", "firstname") + "." + context.getValue("Text Data Bank", "lastname") + "@maheeka.me"
}

context.getValue("Text Data Bank", "firstname")  code segment means to get the column 'firstname' from the data bank named 'Text Data Bank'. If you renamed the data bank, modify this code accordingly.

Now we can make a request to this service using Postman as below.

We did a sample of extracting query parameters here. However, we can extract any header using the same steps.