Skip to Content
Author's profile photo Sriprasad Shivaram Bhat

[SAP Cloud Platform-Integration] Content Filter in Detail

Introduction:

This blog is to demonstrate usage of content Filter step of message Transformation in SAP Cloud Platform Integration.

Content Filter step filters required node or list of nodes or value of specific node from the incoming XML message.

Content Filter consist of below

Name Valid Logical name for Filter
XPath Expression Enter an XPATH to extract a node in the message
Value Type Specify the type for the value you want to extract from
XML Node

Below table provides the different type of Value Type returned from Filter.

String Returns the String value from Node INPUT:
<NODE>VALUE1</NODE>
XPATH: //NODE
OUTPUT: VALUE1
Integer Returns the Integer value from Node INPUT:<NODE>1</NODE>
XPATH: //NODE
OUTPUT: 1
Boolean Returns the Boolean value from Node INPUT:
<NODE>VALUE1</NODE>
XPATH: //NODE
OUTPUT: True
Node Returns the Node value from input xml INPUT:
<NODE>VALUE1</NODE>
XPATH: //NODE
OUTPUT:
<NODE>VALUE1</NODE>
Nodelist Returns list of nodes from incoming XML INPUT:
<Root>
<NODE>VALUE1</NODE>
<NODE1>VALUE1</NODE1>
</Root>
XPATH: //NODE
OUTPUT:
<Root>
<NODE>VALUE1</NODE>
<NODE1>VALUE1</NODE1>
</Root>

Use Cases:

Since the Value Types with Sting,Integer,Boolean and Node are self explanatory will get into Nodelist which we use more often in Custom Integration.

Case#1:

Filter the incoming XML containing <ErrorNode>

Input:

XPATH:

/Root/Record[Error]

Output:

Case#2:

Filters the Record node which contains <Status> node with value S [ Success ] or SK [ Skipped ].

Input:

XPATH:

/Root/Record[(Log/Status/text()= ‘S’ ) or (Log/Status/text() = ‘SK’ )]

Output:

Case#3:

Filters the Record node which contains <Data1> node with value having string length greater than or equal to 2 and <Data2> value not equal to blank.

Input:

XPATH:

/Root/Record[((string-length(Data1))>=2) and (Data2!=”)]

Output:

Case#4:

Filter the incoming XML not containing <ErrorNode>

Input:

XPATH:

/Root/Record[not(Error)]

Output:

Case#5:

Filter the incoming XML record containing  only values which are present in Property .

Input:

Content Modifier:

XPATH:

/Root/Record[contains($PropData1,Data1)]

Output:

Design Use Case:

Lets take a example  that you need to perform action on input data containing both valid and invalid data and need to take further action on only valid set of data.Whenever we get this kind of requirement we use to go with Splitter and Gather ( Since we are expecting group of records post validation ) and in between we will try to route the invalid data but you will end up in error ( Since Router step is not allowed between Splitter and Gather ). Content Filter comes to your help when you have these kind of requirement ( Same will be demonstrated in below image ) where 2 difference branches will have set of valid and invalid data .

Limitation:

  • It works only for XML messages:
  • Content Modifier to be used post Filter step to rebuild the Valid XML since Filter removes the Root node.

References:

Conclusion :

Very useful step which can be leveraged for data validation or filter and group incoming XML based on some condition.

Thanks to my friend Vinay for helping out in few use cases.:)

Regards,

Sriprasad Shivaram Bhat

 

Assigned Tags

      24 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo aravind pujari
      aravind pujari

      Excellent Explanation  and Thanks Sriprasad for sharing.

      Author's profile photo Biplab Das
      Biplab Das

      Well explained. Is it possible to use multiple and complex x-path expressions?

      For example - consider a scenario where employees without " Compensation" information and "nationalID should be filtered out from the Successfactors "Compound Employee" API XML. Is it possible achieve this with content filter?

       

      Author's profile photo Sriprasad Shivaram Bhat
      Sriprasad Shivaram Bhat
      Blog Post Author

      Hello Biplab,

      Its possible to have complex condition also ,but you need to make sure these conditions are grouped together in proper manner.

      I have just created a condition for above case including few more cases.

      queryCompoundEmployeeResponse/CompoundEmployee[((person/logon_user_is_active = 'true') and ((person/employment_information/job_information/emplStatus ='A') and (person/employment_information/job_information/emplStatus/event_reason ='HIRNEW')) and (person/employment_information/compensation_information) and (person/national_id_card)) ]

      Regards,

      Sriprasad Shivaram Bhat

      Author's profile photo Former Member
      Former Member

      Good one Sri and keep blogging!

      Author's profile photo Aditya W. Sharma
      Aditya W. Sharma

      Very nicely explained with use cases, it would be a lot of benefit for developers in HCI to implement requirements based on your use cases. Keep blogging and sharing

      Author's profile photo vinay kumar halale
      vinay kumar halale

      Thanks Shri, Very nice blog.

       

      Thanks for sharing.

       

      Author's profile photo Gagandeep Batra
      Gagandeep Batra

      Great Sri...

      Thanks for Sharing...

      Hope more to come 🙂 🙂

       

      Regards

      Gagan

       

      Author's profile photo Gayathri Narayana
      Gayathri Narayana

      Great amount of detail !! keep blogging:)

      Author's profile photo Former Member
      Former Member

      Helps me a lot. Great Job Sriprasad.

       

      Author's profile photo Rajesh nimmakayala
      Rajesh nimmakayala

       

      Hi Sriprasad Shivaram Bhat , Sriprasad Shivaram Bhat ,

      Its very informative.One query Is it possible to use multiple expressions to filter SF response of queryCompoundEmployeeResponse XML ?

      Example: Consider a scenario where employees job_information records in response of SuccessFactors query need to be sorted in HCI and only one record job_information(Latest and needs to be sort by end_date) should be send to receiver payload XML by filtering/removing all other Job information records of the employee from the Successfactors “Compound Employee” API XML. Is it possible achieve this with content filter?

      Thanks,
      Rajesh N

      Author's profile photo Ashwini Pandey
      Ashwini Pandey

      Very nice blog. Explained with all possible scenarios

      Author's profile photo Roland Marquez
      Roland Marquez

      How Can I do this?

       

      • Content Modifier to be used post Filter step to rebuild the Valid XML since Filter removes the Root node.

       

      Author's profile photo Nitin Deshpande
      Nitin Deshpande

      Hello Roland,

      You can do it in the below way, under your content modifier tab -

      <root>

      ${in.body}

      </root>

       

      Regards,

      Nitin Deshpande

       

      Author's profile photo Axel Albrecht
      Axel Albrecht

      Update: Router step is meanwhile allowed between Splitter and Gather.

      Author's profile photo Shreyashri Kar
      Shreyashri Kar

      I have tried putting a router step between Splitter and Gather but there seems to be some anomaly.

      The Gather is put after 2nd branch of Router, Hence ideally its supposed to be collecting the records which suffice only the condition satisfied in the 2nd branch.

      But here Gather step is collating the records from both the router branches.

      Any idea how to solve this?

      Author's profile photo Axel Albrecht
      Axel Albrecht

      Hi, sorry for the late reply.

      The behavior is correct. The gather will get all items of the splitter, no matter if you end them into the Gather step or not.

      My proposal is to add some empty entries for the items that you don't need, and after the Gather step you can remove them or ignore them.

      Hope that helps!

      Author's profile photo Aswini Alapati
      Aswini Alapati

      Hi Sriprasad Shivaram Bhat ,

      I have a requirement where I need to filter parent node depending on the child node  attribute value . I tried the below attached logic , but result is not as expected . Looking for helpful inputs.

       

      Logic in Filter Node:

       

      Payload: 

       

      Thanks in advance,

      Aswini.

       

       

      Author's profile photo Nagarjuna Sreerambhatla
      Nagarjuna Sreerambhatla

      Hi Siva,

      I need to use complex filter on CE response.

       

      Job Code contains 'RJC' (and) exclude Job Title is equal to 'Cleaner'

      (OR)

      Job Title contains 'Regional Manager'

      (OR)

      Job Title contains 'Regional Manager'

       

      Filter I have provided:

      queryCompoundEmployeeResponse/CompoundEmployee[((person/employment_information/job_information[contains($PropCode1,job_code)] and (person/employment_information/job_information/job_title!='Cleaner')) or (person/employment_information/job_information[contains($PropTitle1,job_title)]))]

      This is not giving the expected results, please advice.

      Nag

       

      Author's profile photo Shreyashri Kar
      Shreyashri Kar

      Hi Sriprasad Shivaram Bhat ,

      Very effective blog... Thanks for the detailed explanation!

      Here I have seen that the Error node appears as a child node of the main Record node. I had a situation where Record & Error nodes both are generated as child nodes of the Parent Root node.

      Root --> Record

      --> Error

      So will the filter step be applicable here if I want to log the Error details in one branch & carry forward the Records in another branch.

      Appreciate your response.

       

      Author's profile photo Dhaladhuli Veera Pani Sarat Chandra
      Dhaladhuli Veera Pani Sarat Chandra

      My incoming XML is as below. As per the requirement we must exclude ‘LEE_000001’ and retain ‘LEE_000029’ based on the values mentioned in the property as externalized parameters in content modifier

      <FOLocation>

      <externalCode>LOC_000045</externalCode>

      <nameTranslationNav>

      <FoTranslation>

      <value_ja_JP/>

      </FoTranslation>

      </nameTranslationNav>

      <addressNavDEFLT>

      <FOCorporateAddressDEFLT>

      <state>18915</state>

      </FOCorporateAddressDEFLT>

      </addressNavDEFLT>

      <name>California - Fremont</name>

      <companyFlxNav>

      <FOCompany>

      <externalCode>LEE_000001</externalCode>

      </FOCompany>

      <FOCompany>

      <externalCode>LEE_000029</externalCode>

      </FOCompany>

      </companyFlxNav>

      </FOLocation>

       

      I  followed the steps mentioned in the blog

      But am get the output as:

      Whereas the expected output  is

      <FOLocation>

      <externalCode>LOC_000045</externalCode>

      <nameTranslationNav>

      <FoTranslation>

      <value_ja_JP/>

      </FoTranslation>

      </nameTranslationNav>

      <addressNavDEFLT>

      <FOCorporateAddressDEFLT>

      <state>18915</state>

      </FOCorporateAddressDEFLT>

      </addressNavDEFLT>

      <name>California - Fremont</name>

      <companyFlxNav>

      <FOCompany>

      <externalCode>LEE_000001</externalCode>

      </FOCompany>

      </companyFlxNav>

      </FOLocation>

      Can you  please suggest  what  am I missing??

      Author's profile photo Vishal Ingale
      Vishal Ingale

      Really helpful and informative blog! Thanks

      Author's profile photo Sudarshan Patwardhan
      Sudarshan Patwardhan
      <root>
      <sub>
      <empID>123</empID>
      <Name>ABC<//Name>
      </sub>
      <sub>
      <empID></empID>
      <Name>ABC</Name>
      </sub>
      </root>

      I am using a content Filter to filter the nodeList with empty empID.

      I am using the below xPath expression in Filter.

      /root[(sub/empID/text() = '')]

      Deploying which , the artifact throws the below error.

      NoTypeConversionAvailableException: No type converter available to convert from type: net.sf.saxon.dom.DOMNodeList to the required type: javax.xml.transform.sax.SAXSource with value net.sf.saxon.dom.DOMNodeList@6957b780]

      Any idea why am I getting this error?

      Thanks!

      Author's profile photo Dilip Mehra
      Dilip Mehra

      Thanks man! Nice Blog!

      Author's profile photo Prashanth Bharadwaj
      Prashanth Bharadwaj

      Hello Sivaprasad,

      Thank you for the blog. Request you to kindly update the same for exists function as well.

      Thanks in advance!!

      Regards,

      Prashanth