Since we started developing in HANA Cloud Integration we came to appreciate the integration pattern Content Modifier more and more.

It is a very powerful way of creating variables that can be used both inside (using properties) and outside the iFlows (using headers). These variables can contain a single value but also a complete xml message.

There are many ways in which the variables you want to use can be set. Just look at the list of types and you will see:

  • Constant
  • XPath
  • Expression
  • Property
  • External parameter
  • Local variable
  • Global variable

One of the types we have used extensively during our developments is the XPath expression.

This is an easy way of reading the value of an element, e.g. /Order/LineItems/Number/text() returns the value/text in <Number> or for counting the number of occurrences of an element, e.g count(/Order/LineItems) results in the number of <LineItems> in a messages.

Using these XPath expressions in the Content Modifier the results can easily be stored in variables and used throughout the iFlows.

Some examples from real messages coming from Salesforce:

/wp-content/uploads/2016/05/xpath_expressions_946850.png

There are however limits to the usage of XPath expressions in the Content Modifier.

Case 1: XPath returning multiple values

In one of the iFlows we received a messages containing multiple UUID elements, but we only needed the UUIDs belonging to the element AddressInformation and not the UUIDs in the other parts of the message.

Take a look this message (it is part of the response from the querybusinesspartnerin webservice on ByDesign):


<n0:BusinessPartnerByIdentificationResponse_sync xmlns:n0="http://sap.com/xi/SAPGlobal20/Global" xmlns:prx="urn:sap.com:proxy:K7F:/1SAI/TAS37D7D57087649686562C:804">
 <BusinessPartner>
  <UUID>00163e06-fdd4-1ed5-a0bf-81adb3476f60</UUID>
  <InternalID>3000009166</InternalID>
  <CategoryCode>2</CategoryCode>
  <CustomerIndicator>true</CustomerIndicator>
  <SupplierIndicator>true</SupplierIndicator>
  <LifeCycleStatusCode>2</LifeCycleStatusCode>
  <Organisation>
       <CompanyLegalFormCode>32</CompanyLegalFormCode>
       <FirstLineName>Test Customer</FirstLineName>
  </Organisation>
  <AddressInformation>
       <UUID>00163e06-fdd4-1ed5-a0bf-81adb347cf64</UUID>
       <AddressUsage>
            <AddressUsageCode>XXDEFAULT</AddressUsageCode>
       </AddressUsage>
       <Address>
           …
        </Address>
  </AddressInformation>
  <AddressInformation>
       <UUID>00163e06-fdd4-1ed5-a0bf-81adb348af65</UUID>
       <AddressUsage>
            <AddressUsageCode>XXDEFAULT</AddressUsageCode>
       </AddressUsage>
       <Address>
           …
       </Address>
  </AddressInformation>
 </BusinessPartner>
</n0:BusinessPartnerByIdentificationResponse_sync>



As you can see there are three elements UUID, one directly underneath <BusinessPartner> and two underneath <AddressInformation>.

Retrieving the required values of the UUIDs is quite easy with an XPath expression, using the expression /n0:BusinessPartnerByIdentificationResponse_sync/BusinessPartner/AddressInformation/UUID/text()

will get result in:

Text=’00163e06-fdd4-1ed5-a0bf-81adb347cf64′

Text=’00163e06-fdd4-1ed5-a0bf-81adb348af65′

However, when you use this XPath in a header or property variable of the Content Modifier it will only put the first value, i.e. ‘00163e06-fdd4-1ed5-a0bf-81adb347cf64’, in the variable ignoring the second one completely.

We have discussed this with SAP and they confirmed that the Content Modifier works this way.

Since we needed to have both values we turned to Groovy scripting and after experimenting a bit we found that using XMLSlurper was the easiest way to get both values, it only took a couple of lines in Groovy:


import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
       def xml = message.getBody(String.class)
       def completeXml= new XmlSlurper().parseText(xml)
       def AddressUUIDs = completeXml.BusinessPartner.AddressInformation.'**'.findAll{ node-> node.name() == 'UUID' }*.text()
       message.setProperty("AddressUUIDs", AddressUUIDs)
       return message
}






As you can see in the script we use XMLSlurper to put the body of the message into the variable completeXML so we can then use the function findAll to find the UUIDs under the path we have specified, in this case completeXML.BusinessPartner.AddressInformation.

This way the values of UUID that are found are placed in one string separated by a comma:

[00163e06-fdd4-1ed5-a0bf-81adb347cf64, 00163e06-fdd4-1ed5-a0bf-81adb348af65].

This string is put into a property variable called AddressUUIDs and the message is returned.

This last statement is very important because without it the variable will not be set in the message.

Now we had both values in the property and we could query them later on our iFlow.

Case 2: Namespace challenges

We have also used XMLSlurper in a case where we received data from Salesforce and wanted to use an XPath expression but were unable to do so because Salesforce used a default namespace xmlns=urn:partner.soap.sforce.com.

At first we did not understand why a simple XPath expression was not working with this namespace until we tested it with an online XPath test tool.

We wanted to read the session ID from the following Salesforce login response using //sessionId:



<loginResponse xmlns="urn:partner.soap.sforce.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <result>
       <metadataServerUrl>https://salesforce_url</metadataServerUrl>
       <passwordExpired>false</passwordExpired>
       <sandbox>true</sandbox>
       <serverUrl>https://salesforce_url</serverUrl>
       <sessionId>Hliushlasdh32847o31bfaefbB(AS9hfadoif</sessionId>
       <userId>userId</userId>
       <userInfo>
      ….
       </userInfo>
 </result>
</loginResponse>




The online tool gave the following error:

The default (no prefix) Namespace URI for XPath queries is always ” and it cannot be redefined to ‘urn:partner.soap.sforce.com’.

We realized that HCI was probably having the same problems with the namespace and therefore used the XMLSlurper again, which did not have this problem.

We hope that this small bit of groovy can help you too in your developments.

Frank Bakermans, YourIntegration

Martin Jaspers, Q for IT BV

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. Bhavesh Kantilal

    Hello Jaspers,

    I had a similar requirement with regards to the SFDC Session ID XPATH and had ended up writing a XSLT Mapping to anonymize the XML as I have illustrated in this blog of mine – HCI -Integrating SalesForce (SFDC) using HCI -Part 1

    When I was trying to figure out why I could not get the XPATH to working, I was using the XMLTools Plugin of notepad++ which returned the valid output for my XPATH.

    Can you let me know which online tool you had used to evaluate your XPATH so I can also use that for my future tests as obviously Notepad++ does not seem to be consistent to HCI!

    Regards,

    Bhavesh

    (0) 

Leave a Reply