Showing posts with label XML. Show all posts
Showing posts with label XML. Show all posts
Sunday, August 16, 2026

XSLT Conditional Logic: if, choose, when and otherwise

In XSLT (Extensible Stylesheet Language Transformations), we often need to produce different output based on conditions. XSLT gives us two main instructions for this. The xsl:if instruction and the xsl:choose instruction. In XSLT 2.0 or later, we also have a shorter inline syntax. I thought of writing a blog post so others can easily find examples as well.

xsl:if Instruction

Saturday, July 25, 2026

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.

<?xml version="1.0" encoding="UTF-8"?>
<employees>
    <employee>
        <name>Nimal</name>
        <salary>85000</salary>
        <department>Finance</department>
    </employee>
    <employee>
        <name>Amara</name>
        <salary>92000</salary>
        <department>Engineering</department>
    </employee>
    <employee>
        <name>Kasun</name>
        <salary>78000</salary>
        <department>Engineering</department>
    </employee>
</employees>

Sort by name:

Wednesday, July 03, 2024

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

Sunday, December 01, 2019

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>
Data 1


<CodeLists>
    <CodeList>
        <Id>O</Id>
        <Name>Open</Name>
    </CodeList>
    <CodeList>
        <Id>P</Id>
        <Name>Pending</Name>
    </CodeList>
</CodeLists>
Data 2


So here I am going to use WSO2 Enterprise Integrator and its XSLT mediator to filter the results. First I am joining all the elements that need to be hidden into a single Synapse property.


<property name="elementsToBeHide" expression="string-join(//CodeLists/CodeList/Id, ',')" scope="default" type="STRING"/>


Then I am calling my XSLT with elementsToBeHide as a parameter.


<xslt key="conf:/xslts/xslt_FilterResults.xslt">
    <property name="elementsToBeHide" expression="$ctx:elementsToBeHide"/>
</xslt>

My XSLT file is stored in the registry. However, if you are using a Micro Integrator profile, you can add this XSLT as a local entry.  Inside my XSLT document, I am looping all code list elements and check whether each ID exists in 'elementsToBeHide' parameter. You can use the same XSLT Choose Condition to filter data based on matching or not matching scenarios. In my example, if ID is not matching to the current ID, it will be added to Code element.


<?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>
Friday, January 04, 2019

XSLT - Modify Date and DateTime value

If you want to perform date and time related opertions with XSLT 'date' or 'dateTime' values, you can use 'xs:yearMonthDuration' or 'xs:dayTimeDuration' function to achieve this. You can add or reduce years, months, date, hours or even minutes through those functions.


 xs:yearMonthDuration

For this function input value is year month duration and it should 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).
nY- the number of years.
nM- the number of months.

ex: xs:yearMonthDuration('P1Y2M') - 1 Year and 2 Months
ex: xs:yearMonthDuration('-P1Y2M') - Negative 1 Year and 2 Months

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).
nD- the number of days.
T- The date and time separator.
nH- the number of hours.
nM- the number of minutes.
nS - the number of seconds.

ex: xs:dayTimeDuration('P3D') - 3 Days
ex: xs:dayTimeDuration('-P3D') - Negative 3 days
ex: xs:dayTimeDuration('P6DT50H80S') - 6 days, 50 hours, and 80 seconds


Example XSLT :

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" >

  <xsl:output method="text"/>

  <xsl:variable name="dT" as="xs:dateTime"   select="xs:dateTime('2016-02-29T00:00:01')"/>
  <xsl:variable name="d" as="xs:date" select="xs:date('2016-02-29')"/>

  <xsl:template match="/">
       <xsl:text>Add 1 Year and 2 Months : </xsl:text> <xsl:value-of select="($d+ xs:yearMonthDuration('P1Y2M'))"/>
       <xsl:text>&#xA;Negative 1 Year and 2 Month : </xsl:text> <xsl:value-of select="($d+ xs:yearMonthDuration('-P1Y2M'))"/>

       <xsl:text>&#xA;Add 3 Days : </xsl:text> <xsl:value-of select="($dT+ xs:dayTimeDuration('P3D'))"/>
       <xsl:text>&#xA;Negative 3 days : </xsl:text> <xsl:value-of select="($dT+xs:dayTimeDuration('-P3D'))"/>
       <xsl:text>&#xA;Add 6 days, 50 hours, and 80 seconds : </xsl:text> <xsl:value-of select="($dT+ xs:dayTimeDuration('P6DT50H80S'))"/>
  </xsl:template>
</xsl:stylesheet>


More on XSLT:
Monday, April 30, 2018

Payload Factory Mediators for JSON Message

WSO2 ESB/EI PayloadFactory mediator can be used to replace the contents of a message. As an example, if the backend is accepting a different message structure than what you are receiving, you can use PayloadFactory mediator to change the message structure. Other than that, if you want to transform XML payload into JSON or JSON to XML with different message structure you can use this mediator.

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>

Sunday, October 23, 2016

Test Your Web Service - POX

What is Web Service:

"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. 
Friday, February 20, 2015

Remove duplicate XML elements using XSLT

Today I faced an issue where I am receiving a XML message with duplicate elements. So I wanted to remove those duplicate elements using some condition . For that I came up with a XSLT which does that.

My XML input:

<OurGuestsCollection xmlns="http://ws.wso2.org/dataservice">
    <OurGuests>
        <id>2</id>
        <firstname>Sample</firstname>
        <lastname>Sample</lastname>
        <email>One</email>
        <reg_date>2015-02-18T13:59:43.000+05:30</reg_date>
    </OurGuests>
    <OurGuests>
        <id>3</id>
        <firstname>Sample1</firstname>
        <lastname>Sample1</lastname>
        <email>One</email>
        <reg_date>2015-02-18T14:13:18.000+05:30</reg_date>
    </OurGuests>
    <OurGuests>
        <id>4</id>
        <firstname>Sample1</firstname>
        <lastname>Sample1</lastname>
        <email>One1</email>
        <reg_date>2015-02-18T14:16:21.000+05:30</reg_date>
    </OurGuests>
</OurGuestsCollection>

XSLT:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="m0:OurGuests"
        xmlns:m0="http://ws.wso2.org/dataservice">
        <xsl:if test="not(following::m0:OurGuests[m0:firstname=current()/m0:firstname])">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

XML Output :

<OurGuestsCollection xmlns="http://ws.wso2.org/dataservice">
    <OurGuests>
        <id>2</id>
        <firstname>Sample</firstname>
        <lastname>Sample</lastname>
        <email>One</email>
        <reg_date>2015-02-18T13:59:43.000+05:30</reg_date>
    </OurGuests>

    <OurGuests>
        <id>4</id>
        <firstname>Sample1</firstname>
        <lastname>Sample1</lastname>
        <email>One1</email>
        <reg_date>2015-02-18T14:16:21.000+05:30</reg_date>
    </OurGuests>
</OurGuestsCollection>

View Counts

Followers