Simplest way to Convert Flat File to Deeply Nested XML Structures Using Java Mapping
Many 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/Java mappings or third-party conversion agents or inbuilt graphical mapping by using intermediate structures and user defend functions.
Simplest way of achieving these kind of requirements is by using SAX parser. Below are the pros and cons for the same.
Pros:
- When compared to other Java parsers like DOM, JAXB; Complexity of the code wise SAX is the best suitable option for this kind of requirements.
- When compared to graphical mapping; No need of inserting intermediate structure and complex context handling logics and user defined functions.
- SAX is much faster and less memory usage than its counterpart DOM parser
Cons:
- Numbers of Lines of code increases when numbers of fields are more.
Step-By-Step Directions to build in SAP PI:
Step1:
Develop the customized Java mapping code in NWDS and import the jar file into ESR as an archival object.
Below is the code written for Java Mapping.
package com.sappi.practice;
///Normal Java Imports
import java.io.IOException;
import java.io.InputStream;
//SAX imports
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
//Java Mapping Imports
import com.sap.aii.mapping.api.AbstractTransformation;
import com.sap.aii.mapping.api.StreamTransformationException;
import com.sap.aii.mapping.api.TransformationInput;
import com.sap.aii.mapping.api.TransformationOutput;
//Below program is written using PI 7.1 API
public class HierarchialStructuresUsingSAX extends AbstractTransformation {
public void transform(TransformationInput in, TransformationOutput out)
throws StreamTransformationException {
getTrace().addInfo(“JAVA Mapping Called”);
InputStream instream = in.getInputPayload().getInputStream();
getTrace().addInfo(“Input XML Payload is successfuly Read”);
Handling handler = new Handling();
SAXParserFactory factory = SAXParserFactory.newInstance();
String result = null;
try {
SAXParser saxpr = factory.newSAXParser();
saxpr.parse(instream, handler);
} catch (Exception e) {
getTrace().addWarning(“$$$ Exception occured $$$” + e.getMessage());
e.printStackTrace();
getTrace().addInfo(e.getMessage(), e);
}
result = handler.getResult(); //Getting the final Output Structure
try {
out.getOutputPayload().getOutputStream().write(result.getBytes());
getTrace().addInfo(“Output XML Payload is successfuly Written”);
} catch (IOException e) {
getTrace().addWarning(
“$$$ Exception occured while writing the o/p payload $$$”);
e.printStackTrace();
getTrace().addInfo(e.getMessage(), e);
}
}
/* Second class Which extends DefaultHandler */
class Handling extends DefaultHandler {
StringBuffer fresult = new StringBuffer();
private String ITEM_Node = “closed”;
private String ItemDetail_Node = “closed”;
public void startDocument() throws SAXException {
fresult.append(“<?xml version=\”1.0\” encoding=\”UTF-8\”?>”);
fresult.append(“<ns0:ReceiverFile_MT xmlns:ns0=\”Test\”>”);
}
public void endDocument() throws SAXException {
fresult.append(“</ns0:ReceiverFile_MT>”);
}
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
String lName = localName;
if (lName.equals(“”))
lName = qName;
if (lName.equals(“HEADER”)) {
fresult.append(“<HEADER>”);
}
if (lName.equals(“CREATION_DATE”)) {
fresult.append(“<CREATION_DATE>”);
}
if (lName.equals(“CREATION_TIME”)) {
fresult.append(“<CREATION_TIME>”);
}
if (lName.equals(“ITEM”)) {
if (ItemDetail_Node.equalsIgnoreCase(“open”)) {
fresult.append(“</ItemDetail>”);
ItemDetail_Node = “closed”;
}
if (ITEM_Node.equalsIgnoreCase(“open”)) {
fresult.append(“</ITEM>”);
ITEM_Node = “closed”;
}
fresult.append(“<ITEM>”);
ITEM_Node = “open”;
}
if (lName.equals(“OrderNumber”)) {
fresult.append(“<OrderNumber>”);
}
if (lName.equals(“ItemDetail”)) {
if (ItemDetail_Node.equalsIgnoreCase(“open”)) {
fresult.append(“</ItemDetail>”);
ItemDetail_Node = “closed”;
}
fresult.append(“<ItemDetail>”);
ItemDetail_Node = “open”;
}
if (lName.equals(“OrderQualtity”)) {
fresult.append(“<OrderQualtity>”);
}
if (lName.equals(“TotalCost”)) {
fresult.append(“<TotalCost>”);
}
if (lName.equals(“Address”)) {
fresult.append(“<Address>”);
}
if (lName.equals(“HouseNumber”)) {
fresult.append(“<HouseNumber>”);
}
if (lName.equals(“Street”)) {
fresult.append(“<Street>”);
}
if (lName.equals(“PostCode”)) {
fresult.append(“<PostCode>”);
}
if (lName.equals(“Trailer”)) {
if (ItemDetail_Node.equalsIgnoreCase(“open”)) {
fresult.append(“</ItemDetail>”);
ItemDetail_Node = “closed”;
}
if (ITEM_Node.equalsIgnoreCase(“open”)) {
fresult.append(“</ITEM>”);
ITEM_Node = “closed”;
}
fresult.append(“<Trailer>”);
}
if (lName.equals(“NoofRecords”)) {
fresult.append(“<NoofRecords>”);
} // Says No of ITEM Records
}
public void endElement(String namespaceURI, String localName,
String qName) throws SAXException {
String lName = localName;
if (lName.equals(“”))
lName = qName;
if (lName.equals(“HEADER”)) {
fresult.append(“</HEADER>”);
}
if (lName.equals(“CREATION_DATE”)) {
fresult.append(“</CREATION_DATE>”);
}
if (lName.equals(“CREATION_TIME”)) {
fresult.append(“</CREATION_TIME>”);
}
if (lName.equals(“OrderNumber”)) {
fresult.append(“</OrderNumber>”);
}
if (lName.equals(“OrderQualtity”)) {
fresult.append(“</OrderQualtity>”);
}
if (lName.equals(“TotalCost”)) {
fresult.append(“</TotalCost>”);
}
if (lName.equals(“Address”)) {
fresult.append(“</Address>”);
}
if (lName.equals(“HouseNumber”)) {
fresult.append(“</HouseNumber>”);
}
if (lName.equals(“Street”)) {
fresult.append(“</Street>”);
}
if (lName.equals(“PostCode”)) {
fresult.append(“</PostCode>”);
}
if (lName.equals(“Trailer”)) {
fresult.append(“</Trailer>”);
}
if (lName.equals(“NoofRecords”)) {
fresult.append(“</NoofRecords>”);
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
String val = new String(ch, start, length);
fresult.append(val);
}
public String getResult() {
return fresult.toString();
}
}
}
Step2:
Build an interface which picks the csv file from System A and transform into target hierarchical structure using the importing java archive in the previous step and post the Output (File, IDoc, etc) into target system B.
Sample Input CSV File
Input XML payload after FCC.
Output XML Payload:
Regards
Venkat
Hi Venkat,
You are helping all the community with a typical problem in the forums. Thanks for sharing!.
Regards.
Thank you... 🙂
Nice blog!!
Thanks Rajeev.
Hi Venkat,
Thanks for the info, the blog waht u have posted is really helpful, but i need some more info., weather this works for multiple records in a single file
Thanks Praveen.
Yes it works .Example I have taken to explain does contain multiple body records in a single file .
Regards
Venkat
Nice informative blog Venkat.
Thanks.
Thank you Anshu Kumar.
Hi Venkat,
It is very informative blog thanks for sharing your knowledge.
Regards,
Avinash
Hi Venkat,
Thank you for sharing this. It really helped.
Regards,
Santhi
Thank you .I'm glad my blog helped.
Regards
Venkat
Hi Gurus,
i have no much experiences with Java and I want to simulate this example by myself.
However I do not understand it clearly.
This Java mapping should be put in an Operation mapping, shouldn't it?
If so, how can i define this service-Interface and message-type inside?
your Explanation would be appreciated.
Sincerely
Sara
Hi Sara,
Can you create separate thread and give the input file and output XML which you expecting it then we can take it from there.
Regards,
Praveen.
Hi Praveen,
thank you for your reminder!
I think it is not neccessary to create a new thread.
I just want to know how this example works without FCC.
thanks and regards
Sara
FCC is needed , FCC converts the flat file to one level XML file and then java mapping is used to convert the one level xml to deeply nested structure.
Aha. That accounts for it!
thanks for the Explanation! I'm too foolish. 😛
Hi Venkat,
Help full blog, could you please give me screenshot of your FCC