Skip to Content
Technical Articles
Author's profile photo Antony FERMINUS

SAP CPI message mapping Flat To Tree Structure

SAP CPI Message mapping Flat Structure to Tree structure which has been briefly explained by Eaksiri Sontisirikul in on the blog. It is a great blog. Thanks Eaksiri.

I was trying expand the payload bit complex and came up with some additional mapping steps.

So I decided to share those information below.

Request payload.

<CompoundEmployee>
	<Person>
		<Manager_ID>1000</Manager_ID>
		<Manager_Name>Manager A</Manager_Name>
		<Employee_ID>8000</Employee_ID>
		<Employee_Name>Emp A</Employee_Name>
	</Person>
	<Person>
		<Manager_ID>1000</Manager_ID>
		<Manager_Name>Manager A</Manager_Name>
		<Employee_ID>8005</Employee_ID>
		<Employee_Name>Emp B</Employee_Name>
	</Person>
	<Person>
		<Manager_ID>2000</Manager_ID>
		<Manager_Name>Manager B</Manager_Name>
		<Employee_ID>9000</Employee_ID>
		<Employee_Name>Emp C</Employee_Name>
	</Person>
	<Person>
		<Manager_ID>2000</Manager_ID>
		<Manager_Name>Manager B</Manager_Name>
		<Employee_ID>9002</Employee_ID>
		<Employee_Name>Emp D</Employee_Name>
	</Person>
	<Person>
		<Manager_ID>1000</Manager_ID>
		<Manager_Name>Manager A</Manager_Name>
		<Employee_ID>9003</Employee_ID>
		<Employee_Name>Emp E</Employee_Name>
	</Person>
	<Person>
		<Manager_ID>3000</Manager_ID>
		<Manager_Name>Manager C</Manager_Name>
		<Employee_ID>9004</Employee_ID>
		<Employee_Name>Emp F</Employee_Name>
	</Person>
	<Person>
		<Manager_ID>2000</Manager_ID>
		<Manager_Name>Manager B</Manager_Name>
		<Employee_ID>9005</Employee_ID>
		<Employee_Name>Emp G</Employee_Name>
	</Person>
</CompoundEmployee>

Response Payload

<CompoundEmployee>
	<Person>
		<Manager_ID>1000</Manager_ID>
		<Manager_Name>Manager A</Manager_Name>
		<Employee>
			<Employee_ID>8000</Employee_ID>
			<Employee_Name>Emp A</Employee_Name>
		</Employee>
		<Employee>
			<Employee_ID>8005</Employee_ID>
			<Employee_Name>Emp B</Employee_Name>
		</Employee>
		<Employee>
			<Employee_ID>9003</Employee_ID>
			<Employee_Name>Emp E</Employee_Name>
		</Employee>
	</Person>
	<Person>
		<Manager_ID>2000</Manager_ID>
		<Manager_Name>Manager B</Manager_Name>
		<Employee>
			<Employee_ID>9000</Employee_ID>
			<Employee_Name>Emp C</Employee_Name>
		</Employee>
		<Employee>
			<Employee_ID>9002</Employee_ID>
			<Employee_Name>Emp D</Employee_Name>
		</Employee>
		<Employee>
			<Employee_ID>9005</Employee_ID>
			<Employee_Name>Emp G</Employee_Name>
		</Employee>
	</Person>
	<Person>
		<Manager_ID>3000</Manager_ID>
		<Manager_Name>Manager C</Manager_Name>
		<Employee>
			<Employee_ID>9004</Employee_ID>
			<Employee_Name>Emp F</Employee_Name>
		</Employee>
	</Person>
</CompoundEmployee>

Simulation

To obtain this result we have to adapt our mapping with ‘sort’, ‘sortByKey’ functions in between.

The Employee_ID, Employee_Name need additional mapping steps too.

 

CompoundEmployee

CompoundEmployee

Person

Manager_ID > removeContext 
           > Sort(case sensitive,asc) 
           > SplitByValue (value change) 
           > collapseContext 
           > Person

Person1

Person2

Person3

 

Manager_ID

Manager_ID > Removecontext 
           > sort(case sencitive, asc) 
           > SplitByValue (value change) 
           > collapseContext 
           > splitByValue 
           > Manager_ID

Manager_ID

 

Manager_Name

Manager_Name1

Manager_Name > removeContext 
             > sort (case sensitive, asc) 
             > splitByValue (Value change) 
             > collapseContext 
             > splitByValue (Each value ) 
             > formatByExample(input) 
             > Manager_Name

Manager_ID > removeContext 
           > sort (case sensitive, asc) 
           > splitByValue (Value change) 
           > collapseContext 
           > splitByValue (Each value ) 
           > formatByExample(pattern) 
           > Manager_Name

Manager_Name2

 

Employee

Employee_ID > formatByExample (input)
            > Employee

Manager_ID > removeContext 
           > sort (case sensitive, asc) 
           > splitByValue (Value change) 
           > formatByExample (pattern) 
           > Employee

Employee1

 

Employee_ID

Manager_ID > removeContext 
           > sortByKey(key) 
           > splitByValue(Each value) 
           > Employee_ID

Emoloyee_ID > removecontext 
            > sortByKey(value)
            > Employee_ID

Employee_ID

 

Employee_Name

             Same mapping as above with Employee_NameEmployee_name

 

Happy reading.

Assigned Tags

      5 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Daniel Graversen
      Daniel Graversen

      Hi

      The scenario is one of the more complicated scenarios to manage in a normal message mapping.

      You need to be really carful and if there are more fields the solutions becomes even bigger challenge.  DO check what happens if an employee name is missing. 

       

      You can also use XSLT

      <?xml version="1.0" encoding="UTF-8"?>
      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"        version="1.0">
          <xsl:output method="xml" indent="yes"/>
      
          <xsl:key name="manager" match="Person" use="Manager_ID"/>
      
          <xsl:template match="/CompoundEmployee">
              <EmployeeList>
                  <xsl:for-each select="Person[count(. | key('manager', Manager_ID)[1]) = 1]">
                      <xsl:sort select="Manager_ID"/>
                      <Manager>
                         <Manager_ID><xsl:value-of select="Manager_ID"/></Manager_ID>
                          <xsl:for-each select="key('manager', Manager_ID)">
      
                              <Employee>
                                 <ID><xsl:value-of select="Employee_ID"/></ID>
                                  <Name><xsl:value-of select="Employee_Name"/></Name>
      
                              </Employee>
                          </xsl:for-each>
                      </Manager>
                  </xsl:for-each>
              </EmployeeList>
          </xsl:template>
      </xsl:stylesheet>
      
      Author's profile photo Antony FERMINUS
      Antony FERMINUS
      Blog Post Author

      Hi Daniel,

      Thanks for the XSLT proposal.

      This scenario is more focused on graphical mapping.

      Of course more complex structure mapping can be handled through XSLT process as you mentioned.

      In case of missing XML elements like Employee_Name or other elements we can have the XML validator to avoid those issues.

       

      Author's profile photo Daniel Graversen
      Daniel Graversen

      Yes structural mappings like this is more challenging in Message Mappings.  And I have also been making such scenarios and trying to clamp everything into just one mappings. In truth you can expand the scope of the mappings quite easily and use more mappings without a big hit on the performance in most cases.

      But developer should consider what makes most sense

      Author's profile photo learning hub
      learning hub

      Very good blog and helpful for people who are from PI PO background and find XSLT and groovy difficult to code.

      Author's profile photo Arpit Kumar Gupta
      Arpit Kumar Gupta

      Hi,

      In my source side, there are children node upto level 4. I want to add a field "PersonID" in my target side alongwith all the childnode of source side, which will group all of them into a single PersonID. This approach is working for me, but also observed that for some navigation it's not working and throwing me error. Please suggest me what can be done to overcome this issue?

      I've used the above approach only. Also for mapping child nodes in the target side, use the same approach adopted to map the target values.

      I've seen few other blogs, and they are suggesting from a simple flat structure and converting it into a tree structure. But in my case, it's already a tree structure.