« Understanding X12 error messages in BizTalk | EDI Validation Errors: Segment Syntax » |
Nested loops to Single Loop
Here is the problem posed by a developer. The input file is:
<Header>
<PONbr>PONbr</PONbr>
<PODate>20100721</PODate>
<Name>Name</Name>
<CustID>CustID
<VendEDICode>VendEDICode</VendorEDICode>
<VendAcct>VendAcct</VendAcct>
<Buyer>Buyer</Buyer>
<POAmt>10.4</POAmt>
<POItemTotal>10.4</POItemTotal>
<LineCntr>10<LineCntr>
<LineItems>
<PONbr></PONbr>
<LineRef>1</LineRef>
<QtyOrd>1</QtyOrd>
<PurchUnit>EA</PurchUnit>
<UnitCost>1</UnitCost>
<VendItemID>11111</VendItemID>
<NDC>11111</NDC>
<UPC>11111</UPC>
<TranDesc>TranDesc11</Transdesc>
</LineItems>
<LineItems>
<PONbr></PONbr>
<LineRef>2</LineRef>
<QtyOrd>2</QtyOrd>
<PurchUnit>EA</PurchUnit>
<UnitCost>2</UnitCost>
<VendItemID>22222</VendItemID>
<NDC>22222</NDC>
<UPC>22222</UPC>
<TransDesc>TranDesc22</Transdesc>
</LineItems>
</Header>
The area of interest is the LineItems node, which is a looping node. There are two instances of this node in the input file. The data inside the LineItems node is flat. The LineItems node data must be output to a target loop, the PO loop. The relationship between the two loops is 1:1, so for the most part this is an easy mapping. The problem is that the PO1 loop has a child loop, the PID loop. Data from the one node in the source, the TransDesc node, must be output in the PID loop. This is a simple instance of one-to-many looping.
Two output loops, one a child of the other, often cannot be driven by the data or with looping functoids. The fact that one loop is a child of the other confuses the mapping engine. There is a simple technique that works in this case. The desired output, looking at only the PO1 loop, is:
<ns0:PO1Loop1>
<ns0:PO1>
<PO101></PO101>
<PO102>1</PO102>
<PO103>EA</PO103>
<PO104>1</PO104>
<PO106>VN</PO106>
<PO107>11111</PO107>
<PO108>ND</PO108>
<PO109>11111</PO109>
<PO110>UP</PO110>
<PO111>11111</PO111>
</ns0:PO1>
<ns0:PID_2>
<PID01>F</PID01>
<PID05>TranDesc11</PID05>
</ns0:PID_2>
</ns0:PIDLoop1>
<ns0:PO1Loop1>
<ns0:PO1>
<PO101></PO101>
<PO102>2</PO102>
<PO103>EA</PO103>
<PO104>2</PO104>
<PO106>VN</PO106>
<PO107>22222</PO107>
<PO108>ND</PO108>
<PO109>22222</PO109>
<PO110>UP</PO110>
<PO111>22222</PO111>
</ns0:PO1>
<ns0:PID_2>
<PID01>F</PID01>
<PID05>TranDesc22</PID05>
</ns0:PID_2>
</ns0:PIDLoop1>
The PO1 portion of the map is shown in the figure below. The looping functoid ensures that one PO1Loop1 is created for each source LineItems node. The three Uppercase functoids put constants into their target nodes. Everything else is a simple mapping link from source node to target node.
The code in the Scripting functoid is:
<!--******************************************************
Creates the PID segment
*******************************************************-->
<xsl:template name="PID">
<xsl:param name="description" />
<xsl:if test="$description != ''''">
<xsl:element name="ns0:PIDLoop1">
<xsl:element name="ns0:PID_2">
<xsl:element name="PID01">F</xsl:element>
<xsl:element name="PID05"><xsl:value-of select="$description"/></xsl:element>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:template>
The data from the TranDesc node is the input to the script. The script uses XSLT to build the entire PIDLoop1 node, including the PID_2 node and the PID101 and PID102 data nodes.
This same technique can be used in many other similar instances, most notably to force creation of N3 nodes in an N1 loop.