on 10-14-2010 8:17 AM
Hi Gurus,
The following is the response message i am getting after the mapping
<ns1:MT_MATRES>
<MATERIAL_DETAILS>
<MATERIAL>MAT</MATERIAL>
<MATL_DESC> stainless steel</MATL_DESC>
<MATL_TYPE>ROH</MATL_TYPE>
<MATL_GROUP>FILES</MATL_GROUP>
<GROSS_WT>0</GROSS_WT>
<NET_WEIGHT>0</NET_WEIGHT>
<BASE_UOM>KG</BASE_UOM>
<PUR_GROUP/>
<STD_PRICE>0</STD_PRICE>
<PRICE_UNIT>0</PRICE_UNIT>
</MATERIAL_DETAILS>
<RETURN>
<TYPE>S</TYPE>
<CODE/>
<MESSAGE/>
</RETURN>
</ns1:MT_MATRES>
I want to remove the <ns1:MT_MATRES> node from the above response message and send the rest to an external system.
How can i remove it?
Thanks,
Prabu
Hi
use this module in your adapter before standard adapter module
AF_Modules/XMLAnonymizerBean as local EB and following key anonymizer.acceptNamespaces
Regards
M.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You can remove the namespace declaration and the namepsace prefix, when you go to your message type and remove the entry in the field XML Namespace.
If you want to rename the root name, rename the message type, as the message type name is the root name.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks all for you replies.
The requirement has changed a little and i have opened a new thread "return a response based on condition" for that, I would request you post your answers for that as well.
Still all you answers will be helpful to me and other newbies.
Thank you all once again for you support.
Hi All,
After some changes in the requirements and configurations the scenario has changed a little bit.
My response message will be in either of the following structure based on a condition (without name space detail)
<MT_MATRES>
<MATERIAL_DETAILS>
<MATERIAL>MAT</MATERIAL>
<MATL_DESC> stainless steel</MATL_DESC>
<MATL_TYPE>ROH</MATL_TYPE>
<MATL_GROUP>FILES</MATL_GROUP>
<GROSS_WT>0</GROSS_WT>
<NET_WEIGHT>0</NET_WEIGHT>
<BASE_UOM>KG</BASE_UOM>
<PUR_GROUP/>
<STD_PRICE>0</STD_PRICE>
<PRICE_UNIT>0</PRICE_UNIT>
</MATERIAL_DETAILS>
</MT_MATRES>
OR
<MT_MATRES>
<RETURN>
<TYPE>S</TYPE>
<CODE/>
<MESSAGE/>
</RETURN>
<MT_MATRES>
now i have to remove the root node <MT_MATRES> and send the rest with <MATERIAL_DETAILS> or <RETURN>; as the root node, let me know how it can be done.
Thanks,
Prabu
Thanks for the reply Shabarish.
The name space and prefix has been removed already, my requirement is to remove the root node.
for ex: the XML structure after a mapping will look like below
<detail>
<category>
<regular> </regular>
</category>
</detail>
I need to remove the <detail> element from the above structure and return the following
<category>
<regular> </regular>
</category>
Let me know how to do that using a XSLT mapping. Any other method also will do.
Thanks,
Prabu
I haven't tried this out, but since you have marked Shweta's solution as very useful, I would suggest to use the following java mapping. I have marked the changes in bold :
import java.io.*;
import java.util.*;
import com.sap.aii.mapping.api.*;
public class RemoveMessageType implements StreamTransformation {
String record=null;
String comment=null;
private Map param = null;
private AbstractTrace trace = null;
public void execute(InputStream in, OutputStream out) {
try {
DataInputStream stdin = new DataInputStream(in);
int length = getLengthFromStream(stdin);
stdin.reset();
byte[] buffer = getBytesFromStream(stdin);
String sub=null;
String str = new String(buffer);
String response = "";
String messageType = "<ns1:MT_MATRES>";
String responseEnd = "";
String messageTypeEnd = "</ns1:MT_MATRES>";
str = str.replaceAll(messageType,response);
str = str.replaceAll(messageTypeEnd,responseEnd);
out.write(str.getBytes());
out.close();
} catch (IOException e) {
}
}
public int getLengthFromStream(InputStream is ) throws
IOException{
int i = 0;
int length = 0;
try{
while ((i = is.read())> 0){
length ++;
}
}catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
return length;
}
public byte[] getBytesFromStream(InputStream is) throws
IOException {
// Create the byte array to hold the data
byte[] bytes = new bytegetLengthFromStream(is);
is.reset();
// Read in the bytes
int offset = 0;
int tmp = 0;
while (offset < bytes.length
&& (is.read(bytes, offset, offset +
(tmp = is.available()))) > 0) {
offset += tmp;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read Inputstream");
}
// Close the input stream and return bytes
is.close();
return bytes;
}
public void setParameter (Map param) {
this.param = param;
if (param == null) {
this.param = new HashMap();
}
}
}
Regards,
TK
Thanks Sameej.
Let me know where to deploy this as my response mapping is as follows
BAPI.Response-->Response
Response has the resultant structure as below, from which <MT_MATRES> has to be stripped.
<MT_MATRES>
<element1>
<element1_1></element1_1>
</element1>
</MT_MATRES>
Note the element names may change dynamically (that part is already taken care in the response mapping).
The Idea is to remove the wrapper root node.
Thanks,
Prabu
> Note the element names may change dynamically (that part is already taken care in the response mapping).
>
> The Idea is to remove the wrapper root node.
My idea is that you discuss that structure again.
A response message should have a unique root node.
When you have several possible root nodes for a response, that is a bad design.
As PI expert you have to influence the design of the interfaces, if business people want to use bad design, you have to prevent this.
Hi Stefan,
The idea is to return success or error details for an entity based on the condition.
The resultant structure is the output of mapping using CREATEIF which we've discussed in the below thread
Everything is working fine but the message type wraps the output structure as the root node which I wan to remove.
This is necessary because we don't have a luxury to change the .NET interfaces which sends the request and gets response from PI. Hope you understand the situation.
Let me know a good solution and I am ready to start over.
Thanks,
Prabu
Hi All,
Solved it myself using XSLT mapping.
I have not renamed the root but removed it.
For people like me who may need it in future, this is how i did it.
used the following XSL mapping after the final graphical mapping in the response (from BAPI)
***************************************************************************
<xsl:template match="/">
<xsl:for-each select="/Response/Mat_det">
<xsl:element name="Mat_det">
<xsl:element name="Mat_desc">
<xsl:value-of select="Mat_desc"/>
</xsl:element>
<xsl:element name="Mat_type">
<xsl:value-of select="Mat_type"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
<xsl:for-each select="/Response/ErrorDetails">
<xsl:element name="ErrorDetails">
<xsl:element name="ErrorCode">
<xsl:value-of select="ErrorCode"/>
</xsl:element>
<xsl:element name="ErrorMessage">
<xsl:value-of select="ErrorMessage"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:template>
**********************************************************************************
Thanks for your encouraging answers
Prabu
You can use Java or XSLT mapping to perform this.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Prabhu,
Please use following java mapping to replace MT_ with <response>:
import java.io.*;
import java.util.*;
import com.sap.aii.mapping.api.*;
public class RemoveMessageType implements StreamTransformation {
String record=null;
String comment=null;
private Map param = null;
private AbstractTrace trace = null;
public void execute(InputStream in, OutputStream out) {
try {
DataInputStream stdin = new DataInputStream(in);
int length = getLengthFromStream(stdin);
stdin.reset();
byte[] buffer = getBytesFromStream(stdin);
String sub=null;
String str = new String(buffer);
String response = "<response>";
String messageType = "<ns1:MT_MATRES>";
String responseEnd = "</response>";
String messageTypeEnd = "</ns1:MT_MATRES>";
str = str.replaceAll(messageType,response);
str = str.replaceAll(messageTypeEnd,responseEnd);
out.write(str.getBytes());
out.close();
} catch (IOException e) {
}
}
public int getLengthFromStream(InputStream is ) throws
IOException{
int i = 0;
int length = 0;
try{
while ((i = is.read())> 0){
length ++;
}
}catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
}
return length;
}
public byte[] getBytesFromStream(InputStream is) throws
IOException {
// Create the byte array to hold the data
byte[] bytes = new byte[getLengthFromStream(is)];
is.reset();
// Read in the bytes
int offset = 0;
int tmp = 0;
while (offset < bytes.length
&& (is.read(bytes, offset, offset +
(tmp = is.available()))) > 0) {
offset += tmp;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read Inputstream");
}
// Close the input stream and return bytes
is.close();
return bytes;
}
public void setParameter (Map param) {
this.param = param;
if (param == null) {
this.param = new HashMap();
}
}
}
Thanks.
Regards,
Shweta
Hi,
Not sure you can have an XML document w/o a root node ! If you remove the MATRES root node, it will contain 2 main nodes ... To remove the namespace prefix, I think the MessageAnonymizerBean should make it (not fully sure about the bean name) ...
Rgds
Chris
Edited by: Christophe PFERTZEL on Oct 14, 2010 9:37 AM
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Try this, I tested this in standalone mode and it is working.
import com.sap.aii.mapping.api.StreamTransformation;
import java.io.*;
import java.util.Map;
public class RemoveNodeSample
implements StreamTransformation
{
public RemoveNodeSample()
{ }
public void setParameter(Map map1)
{
map = map1;
}
public static void main(String args[])
{
try
{
FileInputStream fin = new FileInputStream(args[0]);
FileOutputStream fout = new FileOutputStream(args[1]);
RemoveNodeSample mapping = new RemoveNodeSample();
mapping.execute(fin, fout);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void execute(InputStream inputstream, OutputStream outputstream)
{
int len = 0;
int BUFFER = 2048;
byte buf[] = new byte[BUFFER];
try
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((len = inputstream.read(buf)) != -1)
{
baos.write(buf, 0, len);
}
String line = new String(baos.toByteArray() );
String removeNodes = line.substring(0, line.indexOf("<ns1:MT_MATRES>")) + line.substring(line.indexOf("<ns1:MT_MATRES>") + "<ns1:MT_MATRES>".length() , line.indexOf("</ns1:MT_MATRES>"));
outputstream.write(removeNodes.getBytes());
//System.out.println(removeNodes);
}
catch (Exception e)
{
e.printStackTrace();
}
}
private Map map;
}
Edited by: Praveen Gujjeti on Oct 14, 2010 1:51 PM
one solution is create XSD , and use it in PI . in this cases you no need to create staructure manually, you will not find these tags in message.
Regards,
Raj
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
86 | |
10 | |
10 | |
9 | |
6 | |
6 | |
6 | |
5 | |
4 | |
3 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.