XSLT Conditional Logic: if, choose, when and otherwise
XSLT Sorting with xsl:sort
Sorting is a very common requirement in XSLT transformations. XSLT gives us the xsl:sort instruction for this. It works inside xsl:for-each and inside xsl:apply-templates. While working on integration scenarios, I have used almost every option of xsl:sort. I thought of writing a blog post so others can easily find examples as well.
Basic Sorting
The xsl:sort instruction must be the first child of xsl:for-each. The select attribute defines the sort key.
Sort by name:
XSLT Date and Time Manipulation
In XSLT (Extensible Stylesheet Language Transformations) 2.0 or later, we can perform several date and time manipulation processes. I thought of writing a blog post so others can easily find examples as well.
Basic Date & Time XSLT Functions:
current-date() - Returns the current date of the server that XSLT runs
current-time() - Returns the current time of the server that XSLT runs
current-dateTime() - Returns the current date and time of the server that XSLT runs
implicit-timezone() - Returns the implicit time zone of the server that XSLT runs
Compare Two XML Elements and Filter using WSO2 MI
Think about an integration scenario, where you are getting a list of data from a service endpoint(Data 1) and you want to exclude or match this response against the data returned by another service endpoint(Data 2).
In such a situation, first, you need to have a unique attribute in both data set to exclude or match elements. So in my use case, list of data and matching content is as below
<CodeLists> <CodeList> <Id>O</Id> <Name>Open</Name> </CodeList> <CodeList> <Id>C</Id> <Name>Cancelled</Name> </CodeList> <CodeList> <Id>X</Id> <Name>Denied</Name> </CodeList> <CodeList> <Id>P</Id> <Name>Pending</Name> </CodeList> <CodeList> <Id>D</Id> <Name>Duplicate</Name> </CodeList> </CodeLists>
<CodeLists> <CodeList> <Id>O</Id> <Name>Open</Name> </CodeList> <CodeList> <Id>P</Id> <Name>Pending</Name> </CodeList> </CodeLists>
<property name="elementsToBeHide" expression="string-join(//CodeLists/CodeList/Id, ',')" scope="default" type="STRING"/>
<xslt key="conf:/xslts/xslt_FilterResults.xslt"> <property name="elementsToBeHide" expression="$ctx:elementsToBeHide"/> </xslt>
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sy="http://ws.apache.org/ns/synapse" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <xsl:strip-space elements="*" /> <xsl:param name="elementsToBeHide" /> <xsl:template match="/CodeLists"> <CodeLists> <CodeList> <xsl:for-each select="CodeList"> <xsl:choose> <xsl:when test="matches($elementsToBeHide,Id)"> <!-- match senarios --> </xsl:when> <xsl:otherwise> <!-- not matching --> <Code> <Name><xsl:value-of select="Name"/></Name> <Id><xsl:value-of select="Id"/></Id> </Code> </xsl:otherwise> </xsl:choose> </xsl:for-each> </CodeList> </CodeLists> </xsl:template> </xsl:stylesheet>
The output of the XSLT transformation is as below and it only includes elements which are not matching to the filtering data set.
<CodeLists> <CodeList> <Code> <Id>C</Id> <Name>Cancelled</Name> </Code> <Code> <Id>X</Id> <Name>Denied</Name> </Code> <Code> <Id>D</Id> <Name>Duplicate</Name> </Code> </CodeList> </CodeLists>
XSLT - Modify Date and DateTime value
xs:yearMonthDuration
For this function input value is year month duration and it should be passed in ISO_8601 format
P - The duration designator(for period).
xs:dayTimeDuration
For this function input value is day time duration and it also needs to be passed in ISO_8601 format
n- the [n] is replaced by the value for each of the date and time elements
P - The duration designator(for period).
Example XSLT :
Payload Factory Mediators for JSON Message
Recently, I faced an issue while transforming a message into JSON which is originally read from a CSV file(using Smooks Mediator). This message can have empty values in the content sometimes and such messages look like below:
<Users>
<User>
<FirstName>Chandana</FirstName>
<MiddleName/>
</Users>
</User>
I initially wrote a payload factory mediator like below:
<payloadFactory media-type="json">
<format>
{
"UserInfo": {
"fName": "$1",
"mName": "$2"
}
}
</format>
<args>
<arg evaluator="xml" expression="//User/FirstName"/>
<arg evaluator="xml" expression="//User/MiddleName"/>
</args>
</payloadFactory>
JSON Output from the Payloadfactory mediator :
{
"UserInfo": {
"fName": "Chandana",
"mName": "{"MiddleName":null}",
}
}
So you can see that JSON output is malformed, but this will work perfectly when you have a value for MiddleName field.
To avoid this issue, what we have to do is, when we are passing arguments to the PayloadFactory mediator, we should pass text values(ex: FirstName/text()) instead of the XML object.
<payloadFactory media-type="json">
<format>
{
"UserInfo": {
"fName": "$1",
"mName": "$2"
}
}
</format>
<args>
<arg evaluator="xml" expression="//User/FirstName/text()"/>
<arg evaluator="xml" expression="//User/MiddleName/text()"/>
</args>
</payloadFactory>
Test Your Web Service - POX
"Web Service" is described as a standardized way of communicating and integrating different systems. This communication primarily happens over HTTP.
When testing a Web Service, there are multiple tools and options available. With this "Test your Web Service" post, I am going to publish about few approaches to test a Web Service. In the first post, I use POX based approach to test it.
Testing Your Web Service using POX:
POX(Plain Old XML) means exchanging plain old XML documents over HTTP, and this is a subset of REST. Here you can parse values to the Web Service as URL query parameters.
In this post, I am going to use the Global Weather service available online in below URL. It can be named as the web service URL.
Web service URL : http://www.webservicex.com/globalweather.asmx
You can see the contract(WSDL) of the test web service by navigating to the below URL: http://www.webservicex.com/globalweather.asmx?wsdl
So there you can see this Web Service supports two operations and they are "GetWeather" and "GetCitiesByCountry". Here I am going to invoke the "GetCitiesByCountry" operation in POX way.
You can compose the web service URL to invoke an operation by appending the operation name to the end of the service URL.
http://www.webservicex.com/globalweather.asmx/GetCitiesByCountry
Then to pass the query parameters to the operation you can use the "?" and name/value pairs of the parameters (?CountryName=Australia). For multiple parameters "&" should be used in between parameters.
For that open your browser and enter the following URL: http://www.webservicex.com/globalweather.asmx/GetCitiesByCountry?CountryName=Australia
This will display all the cities supported by this weather check web service.
Remove duplicate XML elements using XSLT
My XML input:
XSLT:
XML Output :