cancel
Showing results for 
Search instead for 
Did you mean: 

Multipart file parsing in PI 7.3 dual stack

former_member201987
Participant
0 Kudos

Hello Experts,

We have a requirement wherein PI should read and parse a file containing multipart data (XML + PDF or word or excel). Please let me know how this can be achieved. A file sender adapter is being used to read these files. We are using PI 7.3 SP07 dual stack.

The format of the file is as below -

<?xml version="1.0" encoding="UTF-8"?><DataResponses>------=_Part_2127_1899305384.1468004618403

content-type:text/xml;charset=UTF-8
content-length:5379
content-id:
<1468004618403.1561744870@app252.snv.ariba.com>


<cXML>

*****Data here****

</cXML>

------=_Part_2127_1899305384.1468004618403
content-type:application/pdf
content-length:44519
content-id:
<574015246.1468004531063@cxml.org>

content-disposition:attachment;filename="Test Attachement DOc.pdf"


%PDF-1.5

%����
1 0 obj
<</Type/Catalog/Pages 2 0 R/Lang(en-US) /StructTreeRoot 13 0 R/MarkInfo<</Marked true>>>>

endobj
2 0 obj
<</Type/Pages/Count 1/Kids[ 3 0 R] >>

endobj
3 0 obj
<</Type/Page/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 7 0 R>>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 612 792] /Contents 4 0 R/Group<</Type/Group/S/Transparency/CS/DeviceRGB>>/Tabs/S/StructParents 0>>

endobj
4 0 obj
<</Filter/FlateDecode/Length 878>>

stream .......................................................

Accepted Solutions (1)

Accepted Solutions (1)

former_member194786
Active Contributor
0 Kudos

Hi Suraj,

You can write a java map to parse the file and create multiple outputs of this data(same as multi-mapping). But that will depend on how you want to process the parsed content in receiver side. If you can provide more information on what your requirement is on the receiver end it will be better easy to provide a more detailed solution.

Regards,

Sanjeev.

former_member201987
Participant
0 Kudos

Thanks Sanjeev!

The XML tags of parsed content need to be mapped to target XML tags (this is already in place except for the pdf content) and the pdf needs to be mapped as a base64binary format in the same target XML in another tag. Please let me know how this can be achieved using Java mapping. Also provide sample code or some links if possible.

Thanks

manoj_khavatkopp
Active Contributor
0 Kudos

Suraj,

You can use the below code to convert the attachment-PDF to Base64binary


String Content = "";

byte[] bt;

String AttachmentID ="";

GlobalContainer globalContainer = container.getGlobalContainer();

InputAttachments inputAttachments = globalContainer.getInputAttachments();

if(inputAttachments.areAttachmentsAvailable())

{

     Collection<String> CollectionIDs = inputAttachments.getAllContentIds(true);

     Object[] arrayObj = CollectionIDs.toArray();

     int attachmentCount = arrayObj.length;

     for(int i =0;i<attachmentCount;i++)

     {

            AttachmentID =(String) arrayObj[i];

              Attachment attachments =inputAttachments.getAttachment(AttachmentID);

       Content = Content + attachments.getBase64EncodedContent();

      }

}

return Content;

And make sure u have marked Read attachment in OM.

Br,

Manoj

former_member194786
Active Contributor
0 Kudos

Hi Suarj,

Here is sample code I could create in between my work:

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

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;

public class parseMultiPartData extends AbstractTransformation{

  /**

   * @param args

   */

  public void transform(TransformationInput arg0, TransformationOutput arg1) throws StreamTransformationException {

    // TODO Auto-generated method stub

    this.execute(arg0.getInputPayload().getInputStream(), arg1.getOutputPayload().getOutputStream());

  }

 

  public void execute(InputStream arg0, OutputStream arg1)

  throws StreamTransformationException {  

   

    try {

      String output = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";

     // InputStream in = arg0;//.getInputPayload().getInputStream();

      BufferedReader reader = new BufferedReader(new InputStreamReader(arg0));

      StringBuilder out = new StringBuilder();

      String line = reader.readLine();

      while(line != null)

      {

        out.append(line + "\n");

        line = reader.readLine();

      }

      String fileContent  = "";

      fileContent = out.toString();

      int fileLength = fileContent.length();

      if(fileLength > 0)

      {

        int XMLStartIndex = fileContent.indexOf("<cXML>");

        int XMLEndIndex = fileContent.indexOf("</cXML>");

        String multipartContent =  fileContent.substring(fileContent.indexOf("<DataResponses>")+15,fileContent.indexOf("content-type:text/xml;charset=UTF-8")-1);

        output += fileContent.substring(XMLStartIndex, XMLEndIndex);

       

        int SecondMultiPart = fileContent.lastIndexOf(multipartContent);

       // System.out.println(fileContent.substring(SecondMultiPart + multipartContent.length(), fileContent.length()));

        output += "<newTag>" + fileContent.substring(SecondMultiPart + multipartContent.length(), fileContent.length()) + "</newTag>";

     

      }

           

      output += "</cXML>";

      arg1.write(output.getBytes()); 

    }

    catch(Exception e){

      throw new StreamTransformationException(e.toString());

       }

  }

 

  public static void main(String[] args) {

    // TODO Auto-generated method stub

    try {

      InputStream in = new FileInputStream(new File("C:\\Users\\Desktop\\Input.txt"));

      OutputStream out = new FileOutputStream(new File("C:\\Users\\Desktop\\output.xml"));

      parseMultiPartData myMapping = new parseMultiPartData();

      myMapping.execute(in , out);

    } catch (Exception e) {

      e.printStackTrace();

    }

  }

}

It will read the content that you provided above and find the cXML content and add a new tag (newTag) in the cXML and then output the data as a single message.

Sample output is below:

<?xml version="1.0" encoding="UTF-8"?><cXML>

*****Data here****

<newTag>

content-type:application/pdf

content-length:44519

content-id:<574015246.1468004531063@cxml.org>

content-disposition:attachment;filename="Test Attachement DOc.pdf"

%PDF-1.5

%����

1 0 obj

<</Type/Catalog/Pages 2 0 R/Lang(en-US) /StructTreeRoot 13 0 R/MarkInfo<</Marked true>>>>

endobj

2 0 obj

<</Type/Pages/Count 1/Kids[ 3 0 R] >>

endobj

3 0 obj

<</Type/Page/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 7 0 R>>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 612 792] /Contents 4 0 R/Group<</Type/Group/S/Transparency/CS/DeviceRGB>>/Tabs/S/StructParents 0>>

endobj

4 0 obj

<</Filter/FlateDecode/Length 878>>

stream .......................................................

</newTag></cXML>

Please note, it's not an optimized code and you will need to perform some more work to get the PDF content etc.

Hope this helps.

Regards,

Sanjeev.

former_member201987
Participant
0 Kudos

Thanks Sanjeev!

I am new to Java, so did not understand if I have to add anything more or this code should work as it is? Also will this code work for multiple parts if more than one documents are being attached to the cXML? Does it also convert the attachments part to base64binary format?

Thanks for your help!

former_member194786
Active Contributor
0 Kudos

Hi Suraj,

I had written code looking at the sample that you had provided. If the data is going to be in same file but with multiple content parts, then you will need to modify the above logic accordingly.

Regarding the conversion to base64binary format, you can use the code from here:

http://javarevisited.blogspot.com.au/2012/02/how-to-encode-decode-string-in-java.html

You will need to import the jars though.

Else, if there are going to be more than 1 file (1 for XML, 1 for pdf etc..), you will have to read those files as additional file in sender channel and then parse the data as per the code provided by Manoj.

BTW, logic that I have used above is to get the index of the elements from where I would need the data from and then got the content from that point onward.


Regards,

Sanjeev.

Answers (1)

Answers (1)

turmoll
Active Contributor
0 Kudos

What about

  1. read file binary by adapter
  2. add custom adapter module that
    1. extracts payload
    2. extracts attachment

?

/k