cancel
Showing results for 
Search instead for 
Did you mean: 

Generate intercalated nodes using graphical mapping

former_member182503
Active Contributor
0 Kudos

Hello experts,

I've a scenario where I have to map the information of one node (Item) to two different and sequencial nodes(ItemA and ItemB).

The source and target structures are shown below:

Source Message example:


<Root>
	<Items>
		<Item>
			<Field1>A1</Field1>
			<Field2>B2</Field2>
			<Field3>C3</Field3>
		</Item>
		<Item>
			<Field1>D1</Field1>
			<Field2>E2</Field2>
			<Field3>F3</Field3>
		</Item>
		<Item>
			<Field1>G1</Field1>
			<Field2>H2</Field2>
			<Field3>I3</Field3>
		</Item>
	</Items>
</Root>

Target Message:


<Root>
	<ItemA>
		<Field1>A1</Field1>
	</ItemA>
	<ItemB>
		<Field2>B2</Field2>
		<Field3>C3</Field3>
	</ItemB>
	<ItemA>
		<Field1>D1</Field1>
	</ItemA>
	<ItemB>
		<Field2>E2</Field2>
		<Field3>F3</Field3>
	</ItemB>
	<ItemA>
		<Field1>G1</Field1>
	</ItemA>
	<ItemB>
		<Field2>H2</Field2>
		<Field3>I3</Field3>
	</ItemB>
</Root>

The main problem here is that I was unable to map the source message to the target message following the sequence of ItemA/ItemB/...

Doing the regular graphical map, I only got this result:


<Root>
	<ItemA>
		<Field1>A1</Field1>
	</ItemA>
	<ItemA>
		<Field1>D1</Field1>
	</ItemA>
	<ItemA>
		<Field1>G1</Field1>
	</ItemA>
	<ItemB>
		<Field2>B2</Field2>
		<Field3>C3</Field3>
	</ItemB>
	<ItemB>
		<Field2>E2</Field2>
		<Field3>F3</Field3>
	</ItemB>
	<ItemB>
		<Field2>H2</Field2>
		<Field3>I3</Field3>
	</ItemB>
</Root>

Is there a way to do this kind of mapping graphically?

Thanks in advance,

José Nunes

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

Hi,

Try to create your target structure as

<Root>

<Record>

<ItemA>

<Field1>A1</Field1>

</ItemA>

<ItemB>

<Field2>B2</Field2>

<Field3>C3</Field3>

</ItemB>

</Record>

</Root>

Map Item to Record

This should resolve the issue

Answers (5)

Answers (5)

anupam_ghosh2
Active Contributor
0 Kudos

Hi Jose Nunes,

This is the java mapping program required to meet your requirements. I have written it for PI 7.0. Please make necessary changes for PI 7.1 .


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.sap.aii.mapping.api.StreamTransformation;
import com.sap.aii.mapping.api.StreamTransformationException;

public class DOMParser2 implements StreamTransformation{




public void execute(InputStream in, OutputStream out)
throws StreamTransformationException {


try
{
	DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
	DocumentBuilder builderel=factory.newDocumentBuilder();
	/*input document in form of XML*/
	Document docIn=builderel.parse(in);
	/*document after parsing*/
	Document docOut=builderel.newDocument();
	TransformerFactory tf=TransformerFactory.newInstance();
	Transformer transform=tf.newTransformer();
	Element root,child=null,child1=null;
	Node textChild;
	
	
	NodeList l;
	int mm,n1;
	boolean b1=false;
	root=docOut.createElement("Root");
	//root.setAttribute("xmlns","urn:bp:xi:hr:edm:test:100");
	l=docIn.getElementsByTagName("Item");
	
	
	n1=l.getLength();
	
	for(mm=0;mm<n1;++mm)
	{
		Node temp;
		for(temp=l.item(mm).getFirstChild();temp!=null;temp=temp.getNextSibling())
		{
			if(temp.getNodeType()== Node.ELEMENT_NODE)
			{
				if(temp.getNodeName().equals("Field1"))
				{
					Node c=temp.getFirstChild();
					child=docOut.createElement("ItemA");
					b1=false;
					if(c!=null)
					{
						child1=docOut.createElement("Field1");
						textChild=docOut.createTextNode(c.getNodeValue());
						child1.appendChild(textChild);
						child.appendChild(child1);
						
					}	
					root.appendChild(child);
					
				}
				else if(temp.getNodeName().equals("Field2"))
				{
					Node c=temp.getFirstChild();
					child=docOut.createElement("ItemB");
					b1=true;
					if(c!=null)
					{
						child1=docOut.createElement("Field2");
						textChild=docOut.createTextNode(c.getNodeValue());
						child1.appendChild(textChild);
						child.appendChild(child1);
					}
					
				}
				else if(temp.getNodeName().equals("Field3"))
				{
					Node c=temp.getFirstChild();
					if(b1==false)
					{
						child=docOut.createElement("ItemB");
					}	
					if(c!=null)
					{
						child1=docOut.createElement("Field3");
						textChild=docOut.createTextNode(c.getNodeValue());
						child1.appendChild(textChild);
						child.appendChild(child1);
					}
					root.appendChild(child);
				}
			}
		}	
	}
 
	
	
	docOut.appendChild(root);
	transform.transform(new DOMSource(docOut), new StreamResult(out)); 
}
catch(Exception e)
{
	e.printStackTrace();
}


}

public void setParameter(Map arg0) {


}

public static void main(String[] args) {
try{
DOMParser2 genFormat=new DOMParser2();
FileInputStream in=new FileInputStream("C:\\Apps\\my folder\\sdn\\input.xml");
FileOutputStream out=new FileOutputStream("C:\\Apps\\my folder\\sdn\\output.xml");
genFormat.execute(in,out);
}
catch(Exception e)
{
e.printStackTrace();
}
}


}


input.xml


<?xml version="1.0" encoding="UTF-8"?>
<Root><ItemA><Field1>A1</Field1></ItemA><ItemB><Field2>B2</Field2><Field3>C3</Field3></ItemB><ItemA><Field1>D1</Field1></ItemA><ItemB><Field2>E2</Field2><Field3>F3</Field3></ItemB><ItemA><Field1>G1</Field1></ItemA><ItemB><Field2>H2</Field2><Field3>I3</Field3></ItemB></Root>

Output.xml


<?xml version="1.0" encoding="UTF-8"?>
<Root><ItemA><Field1>A1</Field1></ItemA><ItemB><Field2>B2</Field2><Field3>C3</Field3></ItemB><ItemA><Field1>D1</Field1></ItemA><ItemB><Field2>E2</Field2><Field3>F3</Field3></ItemB><ItemA><Field1>G1</Field1></ItemA><ItemB><Field2>H2</Field2><Field3>I3</Field3></ItemB></Root>

When I view Output.xml in browser I get this


 <?xml version="1.0" encoding="UTF-8" ?> 
- <Root>
- <ItemA>
  <Field1>A1</Field1> 
  </ItemA>
- <ItemB>
  <Field2>B2</Field2> 
  <Field3>C3</Field3> 
  </ItemB>
- <ItemA>
  <Field1>D1</Field1> 
  </ItemA>
- <ItemB>
  <Field2>E2</Field2> 
  <Field3>F3</Field3> 
  </ItemB>
- <ItemA>
  <Field1>G1</Field1> 
  </ItemA>
- <ItemB>
  <Field2>H2</Field2> 
  <Field3>I3</Field3> 
  </ItemB>
  </Root>

Regards

Anupam

former_member182503
Active Contributor
0 Kudos

Thanks everyone for your valuable input.

I have two constrains that doesn't allow me to do it using Java Mapping or changing the xml structure.

- The customer restrict the use of Java Mapping just in exceptional cases.

- This interface is a RFC to FILE and the FILE will be generated using FCC, so I cannot use a complex XML structure with more than 2 nested nodes.

Despite of the fact that it may not be the best solution, I'm considering to create a xml structure as follow in order to get the expected result.

<Root>
<Recordset>
<Row>
<ItemA>A1</ItemA>
<ItemB>B2C3</ItemB>
</Row>
<Row>
<ItemA>D1</ItemA>
<ItemB>E2F3</ItemB>
</Row>
<Row>
<ItemA>G1</ItemA>
<ItemB>H2I3</ItemB>
</Row>
</Recordset>
</Root>

And set in the communication channel the FCC property Row.fieldSeparator = 'nl'

Best Regards,

José Nunes

Former Member
0 Kudos

Hi

check this Screenshot...

http://postimage.org/image/2esx1q4lg/

Map Recorset (o.unbounded) to item (0 to unbounded)

Regards,

XA

former_member191435
Contributor
0 Kudos

Hi Jose,

U have to create ur structure as below

Record Element 0....unbounded

<ItemA> Element 0..1

fields1 xsd:string 1

</ItemA>

<itemB> Element 0...1

field2 xsd:string 1

field3 xsd:string 1

</ITEMB>

U can map Item A and ItemB record nodes with Constant space. Then u will get ur desired output.

Thanks,

Enivass

0 Kudos

Hi,

Follow the Chandra & Harish Suggestions. if you don't want to change the structure then go for JAVA Mapping.

Regards,

Naga.

Harish
Active Contributor
0 Kudos

Hi,

In graphical mapping you can achieve this by creating ItemA and itemB under Recordset node. So recordset node repeats on the basis of Item from input and you can have the same sequence of itemA and itemB.

Regards,

Harish