Showing posts with label Xpath. Show all posts
Showing posts with label Xpath. Show all posts

Wednesday, October 29, 2014

[WSO2 ESB] Comparing two XMLs and find matching elements using WSO2 ESB 4.8.0

Imagine we are getting a list of xml data from an external service and it is required to match this response against another xml payload and find the matching xml elements inside ESB 4.8.0. For e.g. a user send the below request into ESB.
<Accounts>
    <acctNum>123452</acctNum>
    <acctNum>678912</acctNum>
</Accounts>

Inside ESB we are calling an Account DB service which retrieves all the Account elements inside the database and return us. Assume the BE response with Account details is as follows.

<a123: Accounts xmlns:a123="http://test123.com>

    <a123:Account>
        <a123:AcctNum>123451</a123:
AcctNum>
        <a123:Date>2014-03-26</a123:
Date>
    </a123:Account>
    <a123:Account>
        <a123:AcctNum>123452</a123:
AcctNum>
        <a123:Date>2014-04-20</a123:
Date>
    </a123:Account>
</a123:Accounts>
  
 

   
Once this response comes into ESB it is required to compare the two xmls and retrieve Account elements that matches with account numbers which are in incoming request. We can do this through an iterate mediator inside ESB too, however the way that is explained here is rather simple to be used, specially for a scenario when it is not possible to use Iterate mediator.

1. When the incoming request comes, we can use xpath to get a comma separated String with all account numbers in the request. Then assign it to a Property mediator.

<property name="accountsList" expression="string-join(//Accounts/acctNum, ',')" scope="default" type="STRING"/>
This XPath expression uses string-join() function from Xpath 2.0. Therefore it is required to enable the below property in ESB/repository/conf/synapse.properties file in order to support Xpath 2.0

# Uncomment following to support fallback XPATH 2.0 support with DOM and Saxon
synapse.xpath.dom.failover.
enabled=true   
   
2. Once this property is set we can call the BE and get the Account details response. Then the response payload will be passed to the given XSLT stylesheet using XSLT mediator in ESB.
Also as there is comparison needs to be done here, i am passing the previous 'accountsList' property as a parameter into XSLT stylesheet as well.

<xslt key="MatchingAccounts">
    <property name="AccountsList" expression="$ctx:accountsList"
/>
</xslt>

   
3. The stylesheet is added as a local-entry in the ESB with the name 'MatchingAccounts'. If needed you can add this as a Registry resource too.

<localEntry xmlns="http://ws.apache.org/ns/synapse" key="MatchingAccounts">
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a123="http://test123.com xmlns:fn="http://www.w3.org/2005/xpath-functions" version="2.0">
        <xsl:param name="AccountsList"/>
        <xsl:output method="xml" indent="yes"/>
        <xsl:template match="/">
            <Result xmlns="">
                <xsl:for-each select="//a123:Account">
                    <xsl:if test="matches($AccountsList,
a123:AcctNum)">
                        <xsl:copy-of select="."/>
                    </xsl:if>
                </xsl:for-each>
            </Result>
        </xsl:template>
</xsl:stylesheet>   
</localEntry>

   
4. Inside the style sheet if process through each a123:Account/a123:AcctNum element and checks whether the 'accountsList' String contains that account number. If there is a match that <Account> node is taken as results.

5. For the above two XMLs the final payload that comes outside XSLT mediator will be like this, with one matching Account node.
<Result xmlns="">
    <a123:Account>
        <a123:AcctNum>123452</a123:
AcctNum>
        <a123:Date>2014-04-20</a123:
Date>
    </a123:Account>
</Result>

Sunday, August 31, 2014

[WSO2 ESB] How to Read Local Entries and Registry Entries

This post is rather a quick note to my self. In WSO2 ESB we can have external reference to a file using either a local entry or a registry entry. 

Local-entry :

An entry stored in the local registry. The local registry acts as a memory registry where you can store text strings, XML strings, and URLs. These entries can be retrieved from a mediator.

Registry-entry :
WSO2 ESB makes use of a registry to store various configurations and artifacts such as sequences and endpoints. A registry is a content store and a metadata repository. Various SOA artifacts such as services, WSDLs, and configuration files can be stored in a registry and referred to by a key, which is a path similar to a UNIX file path.

1. This is how we can read some value stores in a local-entry. Let's say i have a value stored in local-entry file 'testEntry'.

<localEntry xmlns="http://ws.apache.org/ns/synapse" key="testEntry">12345</localEntry>

 This is how we can read this value into a mediator.

<property name="testProp" expression="get-property('testEntry')" scope="default" type="STRING"/>

2. If this 'testEntry' file is stored in the registry we have to use 'registry' scope with get-property() XPath extension function and read entry as below.

<property name="testProp" expression="get-property('registry', 'conf://custom/testEntry')" scope="default" type="STRING"/>

[WSO2 ESB] Property mediator : Performing XPath Expressions with and without Namespaces

Assume that we have an XML payload where there are several namespaces defined and we need to retrieve values of some elements from the payload into Properties using XPath. There are several ways to do this. We can either define the namespace in the property mediator and then refer to XML element via XPath with adding the namespace itself into the Xpath operation. let's get started with this.

Below is our payload.

<abc  xmlns="http://abc.xyz.com" >
         <A>YES</A>
         <B>{"abc":"Y","d":"N","e":"N"}</B>
</abc>

For e.g i need to read the value 'A' into a property.  Following are the two ways for this However the 2nd option is more cleaner approach since we can get rid of adding namespace references every where. In addition to Property mediator, this can be used with other mediators in WSO2 ESB whether XPath operations are supported.

1. Use name space entries with property mediator

<property  xmlns:ns="http://abc.xyz.com" name="aValue" expression="//ns:abc/ns:A" scope="default" type="STRING"/>

2. Use local-name() option in XPath in order to avoid name spaces and get the same element value with property mediator.

<property name="aValueWithoutNS" expression="//*[local-name()='A']" scope="default" type="STRING"/>