XI/PI: Convert Flat File to Deeply Nested XML Structures Using Only Graphical Mapping
Many a times, you are required to convert flat file structures to deeply nested structures like IDocs. Standard File Content Conversion allows you to convert the incoming file to flat XML structures only i.e. only one level of nesting is possible. Converting incoming file to deeply nested structures would require use of either custom developed adapter modules or third-party conversion agents.
This article provides a workaround to accomplish the same thing by using only the graphical mapping. William had a similar requirement, and we came up with a generic solution which is described below.
Lets say we have an incoming flat file with structure as described below –
Node1 – Occurs 0..1
Node2 – Occurs 0..unbounded
Node3 – Occurs 0..unbounded
Node4 – Occurs 0..unbounded
And the target structure is as shown below –
Node1 – Occurs 0..1
Node2 – Occurs 0..unbounded
Node3 – Occurs 0..unbounded and repeats under the preceding Node2
Node4 – Occurs 0..unbounded and repeats under the preceding Node3
Due to limitation of the standard File adapter, it is not possible to directly convert the incoming file to the deeply nested target structure. Hence we will use a two step message mapping to attain the required result.
First, we will use file content conversion as shown to covert the incoming file to flat XML structure as supported by the adapter. Click the image on the right to see an enlarged view. We will then use two-step message mapping to convert the flat XML to a nested XML. Figure below shows the flat XML structure generated by the file adapter using file content conversion.

Our aim is to convert the above flat structure to a nested shown below –

Note that there is no common element between parent and child nodes (e.g. Node2 and Node3, or Node3 and Node4) which we could use to determine corresponding parent node for each child node.
Hence, we need to create an intermediate message type which will establish a relationship between the parent and child nodes. We have achieved this by adding id attributes to each of the nodes as shown below.

The id attribute is mapped using a user defined function globalCounter which records the order in which the nodes appear in the source structure. The variable used to store the count is a global variable and is incremented every time a node is found in the source structure (irrespective of the node name).
Create one-to-one message mapping between source message and the intermediate message. Map the id attribute in the target with the globalCounter function.
![]()
The Java code of the globalCounter function is given below –
public String globalCounter(Container container){
GlobalContainer globalContainer;
globalContainer = container.getGlobalContainer();
Object o = globalContainer.getParameter("count");
Integer i;
if ( o == null ) i = new Integer( 0 );
else i = (Integer)o;
i = new Integer(i.intValue() + 1 );
globalContainer.setParameter("count", i );
return i.toString();
}
Now create another message mapping to map the intermediate message type to the target message type. The message mapping is shown below.

Node 1 is directly mapped to Node1 in the target as this node is not part of any hierarchy. The topmost parent node Node2 is mapped using removeContexts function.
![]()
All the nodes appearing below the topmost node (Node3 and Node4 in this case) have been mapped using removeContexts function and user defined nest function as shown below -

The first parameter to the nest function is the id attribute of the parent node while the second parameter is the id attribute of the current node (child node). Both parameters have been first processed with removeContexts function before passing them to the nest function. The third parameter is the actual value of the node that needs to passed on to the target structure. Below is the Java code for the nest function.
public void nest(String[] parent,String[] current,String[] node,ResultList result,Container container){
int i, j;
int a, b, c;
int x;
j = 0;
x = j+1;
for( i = 0; i < current.length; i++ ) {
for (;x<parent.length; j++,x++ ){
a = Integer.parseInt(parent [j]);
b = Integer.parseInt(current [i]);
c = Integer.parseInt(parent [x]);
if ( a < b ) {
if(c > b ) {
result.addValue(node[i]);
break;
}
else if (c < b) {
result.addContextChange();
}
}
}
if (x == parent.length) {
result.addValue(node[i]);
}
}
}
PS: If you are new to the idea of context handling, do read An Introduction to Context Handling.
Once this is done, create an interface mapping between the source and target interface and provide the mapping programs in the correct order i.e. first the mapping between source and intermediate message and then the one between intermediate and target structure. The same is shown below –

Now you can test the interface mapping locally and then test your scenario by doing appropriate directory configuration. Interface mapping test result is shown in the figure below –

Thus, we have seen how we can use plain file adapter and graphical mapping to convert a flat file to a deeply nested XML structure.
This idea could even be extended to convert EDI documents to IDoc structures as an alternative to third-party EDI adapters like Seeburger.


Dharmendra Kumar says:
July 16th, 2008 at 1:31 am
Riyaz,
Blog is very descriptive and very useful. I did the Message mapping and Interface mapping exactly as you described but when I started testing the interface mapping, I am getting the following error message.
Your response is greatly appreaciated.
Runtime exception occurred during execution of application mapping program com/sap/xi/tf/_MM_HCLP_HDOC850_to_ORDERS05bundle_: com.sap.aii.utilxi.misc.api.BaseRuntimeException; RuntimeException in Message-Mapping transformation: Runtime exception during processing target field mapping /ORDERS05/IDOC/E1EDP01/E1EDPT1/E1EDPT2. The message is: Exception:[java.lang.ArrayIndexOutOfBoundsException: 3] in class com.sap.xi.tf._MM_HCLP_HDOC850_to_ORDERS05bundle_ method nest$[com.sap.aii.mappingtool.flib3.Plainer@c2af46, com.sap.aii.mappingtool.flib3.Plainer@18135ac, com.sap.aii.mappingtool.flib3.Plainer@1eacebf]
Riyaz says:
July 16th, 2008 at 10:30 am
Hi Dharmendra,
Cross check the Java code of your UDFs, especially check the for loops. ArrayIndexOutOfBoundsException indicates that the array is running out of bounds when you are looping through it.
Hope this helps.
Regards,
Riyaz
Dharmendra Kumar says:
July 16th, 2008 at 7:46 pm
Riyaz,
Thanks for your comments. In my debugging, I realised that the issue is with Nest function. I think this function designed to support the mandatory nodes (Node1, Node2, Node3 and Node4) on your source mapping and it supports one iteration only. In my case, for every Node1 we can get multiple Node2’s and for every Node2 we can get multiple Node3’s (from 0 to 10). If you have some free time can you help me in fixing the Nest function to support the above requirement. I can provide the sample data for the scenario.
Thanks,
Dharmi.
Riyaz says:
July 17th, 2008 at 9:37 am
Dharmi,
The Nest function is designed in this way - The first argument is the list of id attributes of the node under which you want to create a child node (without any context changes), second argument is the list of id attributes of the node you want to nest under the above parent node (without any context changes) and the third argument is the list of values of the child node (again without any context changes).
So in the above example, we have nested Node3 under Node2. Node1 does not come into picture. The nest function is applied to Node3 i.e. id attributes of Node2 is first argument, id attributes of Node3 is second argument and Node3 itself is the third argument. removeContexts() function is used to pass on a contexts free list of values and is applied to all three arguments. Node2 is mapped only with removeContexts() since it is the topmost node in the hierarchy (Note that Node 1 is out of the hierarchy and is a separate node).
Similarly for Node4, we pass id attributes of Node3 and Node4 as first and second argument and Node4 values as third argument with removeContexts() applied to them before passing them to nest() function.
Since Node2, Node3 and Node4 occur 0..unbounded, they can occur any number of times anywhere. So it very supports multiple occurrences. Thus for every Node2, there can be any number of Node3 nodes and for every Node3 there can be any number of Node4 nodes.
Regards,
Riyaz
Dharmendra Kumar says:
July 18th, 2008 at 2:38 am
Thank you very much for your quick and very detailed response. Looks like your fix is working fine.
I need little more time to validate the data and to let you know the fix is working.
Thanks again for your help.
Dharmi.
Shilpa Singh says:
July 19th, 2008 at 8:49 pm
Hi Riyyaz,
Looks like you are doing a good job for beginers like me
Can you explain me what really the nested loop in nest does, because when I look at it
I have a feeling that X is always j+1. So anything in between will have fraction in it and it will either be truncated down to X or up to J.
so that said
a strictly lesser than b and c strictly greater than b will never occur…… Can you please explain me that logic or send me an email on it.
I will appreciate your help.
Thanks
Shilpa
Riyaz says:
July 21st, 2008 at 9:39 am
Hi Shilpa,
Please go thru the explaination of functionality of nest() function explained in previous comment.
We are working with counters here and are integers always. So fractions wont occur. Also, id of child node will always be greater than its corresponding parent node. so b will always be greater than a and c.
Hope this helps.
Regards,
Riyaz
Venkatesh says:
July 28th, 2008 at 11:36 am
Hi Riyaz,
It looks great to me…
I am also biginner in the SAP XI mapping…
Actually i wanted to convert the deeply nested structure into flat structure…
Any help in this regard will be appreciated….
My mail id is onlyvenkatesh@gmail.com
Regards
Venkatesh
Riyaz says:
July 28th, 2008 at 12:43 pm
Hi Venkatesh,
You can consider taking a reverse approach to this article to convert from deeply nested structure to a flat structure.
Take a look at this thread for inputs.
Regards,
Riyaz
Shwetambari says:
August 25th, 2008 at 2:01 pm
Hi Riyaz,
Your blog “XI/PI: Convert Flat File to Deeply Nested XML Structures Using Only Graphical Mapping” is really good.
My requirement is exactly the opposite of what you explained. I.e. I need to map nested structure (4 hierarchical level) of IDOC to flat structure.
I will really appreciate you can tell me how to achieve this.
Regards,
Shwetambari.
Riyaz says:
August 25th, 2008 at 2:17 pm
Hi Shwetambari,
You can consider taking a reverse approach to this article to convert from deeply nested structure to a flat structure.
Take a look at this thread for inputs.
Regards,
Riyaz