09Sep2013~header~data~data~data~data 09Sep2013~detail~data~data 09Sep2013~detail~data~data 09Sep2013~detail~data~data 10Sep2013~header~data~data~data~data 10Sep2013~detail~data~data 10Sep2013~detail~data~data 10Sep2013~detail~data~data
This is a delimited flat file with tag identifier for header and detail. As you can see, the tag identifiers are not at the beginning of the data for a delimited record. And questioner wants to debatch the file by date.
Figure 1. Flat File Structure.
In the EDI world it is a common practice to precede the tag identifier with batch related information rather than to start with it. Unfortunately however, the BizTalk’s Flat-file schema wizard, doesn’t parse the flat file that way. It expects the tag identifier to be at the beginning of the record. If that is not the case than you will get an error as below:
Figure 2. Flat File schema wizard error for tag identifier not at the beginning.
Following is the schema structure for the above flat file.
Figure 3. Schema Structure.
A way to handle the tag identifier, I prefer Johann Cooper’s suggestion. A generic repeating record to have all the common elements (in this case, just ‘Date’) and choice record node (RecordBatch). Within this choice record, I created separate record for each of the different tag identifiers (‘header’ and ‘detail’) with their respective elements (header children and detail children). Now validating the above flat file instance gave the XML instance like this.
Figure 4. XML instance for the given flat file.
As you can see, the above XML represents the flat file instance, but for debatching it by date, we need to group the record set by date.
Figure 5. XML Instance to group by date element.
We can use the classic Muenchian Method to handle grouping and sorting. In XSLT, Muenchian method is a way to group and sort elements in a more efficient way using keys. Keys work by assigning a key value to a node and giving you easy access to that node through the key value.
Since the main objective is to debatch the file, I created an envelope schema to match this XML structure (whose structure is same as flat file schema) and mapped the flat file schema to envelope schema using Muenchian method based on custom XSLT.
Figure 6. Map Flat file schema to envelope schema.
Muenchian method based mapping.
<?xml version="1.0" encoding="UTF-16"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0" version="1.0" xmlns:ns0="http://MSDN.TechnetWiki.ComplexFFDebatch.EnvelopeSchemaGrouped" xmlns:s0="http://MSDN.TechnetWiki.ComplexFFDebatch.ComplexFFSchemaUngrouped"> <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" /> <xsl:key use="Date" match="/s0:CompleteBatch/Record" name ="groups"/> <xsl:template match="/"> <xsl:apply-templates select="/s0:CompleteBatch" /> </xsl:template> <xsl:template match="/s0:CompleteBatch"> <ns0:CompleteBatch> <!-- In Muenchian grouping , used count() instead of generate-id() for better performance --> <!--<xsl:for-each select="Record[generate-id(.)=generate-id(key('groups',Date))]"> --> <xsl:for-each select="Record[count(.| key('groups',Date)[1])=1]"> <Record> <Date> <xsl:value-of select="Date/text()" /> </Date> <RecordBatch> <xsl:for-each select ="key('groups',Date)"> <xsl:for-each select="RecordBatch/Header"> <Header> <Header_Child1> <xsl:value-of select="Header_Child1/text()" /> </Header_Child1> <Header_Child2> <xsl:value-of select="Header_Child2/text()" /> </Header_Child2> <Header_Child3> <xsl:value-of select="Header_Child3/text()" /> </Header_Child3> <Header_Child4> <xsl:value-of select="Header_Child4/text()" /> </Header_Child4> </Header> </xsl:for-each> <xsl:for-each select="RecordBatch/Detail"> <Detail> <Detail_Child1> <xsl:value-of select="Detail_Child1/text()" /> </Detail_Child1> <Detail_Child2> <xsl:value-of select="Detail_Child2/text()" /> </Detail_Child2> </Detail> </xsl:for-each> </xsl:for-each> </RecordBatch> </Record> </xsl:for-each> </ns0:CompleteBatch> </xsl:template> </xsl:stylesheet>
<?
xml
version
=
"1.0"
encoding
"UTF-16"
?>
<
xsl:stylesheet
xmlns:xsl
"http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl
"urn:schemas-microsoft-com:xslt"
xmlns:var
"http://schemas.microsoft.com/BizTalk/2003/var"
exclude-result-prefixes
"msxsl var s0"
xmlns:ns0
"http://MSDN.TechnetWiki.ComplexFFDebatch.EnvelopeSchemaGrouped"
xmlns:s0
"http://MSDN.TechnetWiki.ComplexFFDebatch.ComplexFFSchemaUngrouped"
>
xsl:output
omit-xml-declaration
"yes"
method
"xml"
/>
xsl:key
use
"Date"
match
"/s0:CompleteBatch/Record"
name
"groups"
xsl:template
"/"
xsl:apply-templates
select
"/s0:CompleteBatch"
</
ns0:CompleteBatch
<!-- In Muenchian grouping , used count() instead of generate-id() for better performance -->
<!--<xsl:for-each select="Record[generate-id(.)=generate-id(key('groups',Date))]"> -->
xsl:for-each
"Record[count(.| key('groups',Date)[1])=1]"
Record
Date
xsl:value-of
"Date/text()"
RecordBatch
"key('groups',Date)"
"RecordBatch/Header"
Header
Header_Child1
"Header_Child1/text()"
Header_Child2
"Header_Child2/text()"
Header_Child3
"Header_Child3/text()"
Header_Child4
"Header_Child4/text()"
"RecordBatch/Detail"
Detail
Detail_Child1
"Detail_Child1/text()"
Detail_Child2
"Detail_Child2/text()"
After applying the map, the XML instance grouped by date would look like this.
Figure 7. XML Instance grouped by date element.
Now with XML being grouped by date in an envelope schema, it can be easily debatched by calling a receive pipeline in Orchestration. I have executed the map in orchestration just to have better readability.
Figure 8. Orchesttration used to call Receive-Pipeline to debatch the message
The output of the debatching is as follows:
Figure 9. Output-Debatched messages.
Read suggested related topics:
Steef-Jan Wiggers edited Revision 25. Comment: Added text
Steef-Jan Wiggers edited Revision 24. Comment: Correcting link
Steef-Jan Wiggers edited Revision 23. Comment: Editing pictures
Steef-Jan Wiggers edited Revision 22. Comment: Minor edit
Steef-Jan Wiggers edited Revision 21. Comment: Added See Also and links
Steef-Jan Wiggers edited Revision 20. Comment: Edits
Maheshkumar S Tiwari edited Revision 1. Comment: Added Tag. Hi Ashwin , good topic for an article ..
Nice article!
Thanks Naomi N.