Paul's Petrov Whiteboard

[BizTalk, Enterprise Application Integration, Business Process Automation, SOA, .NET]

  Home  |   Contact  |   Syndication    |   Login
  67 Posts | 1 Stories | 135 Comments | 30 Trackbacks

News

Archives

Post Categories

Image Galleries

BizTalk

Other

Sunday, January 02, 2011 #

Repeating sequence groups can often be seen in real life XML documents. It happens when certain sequence of elements repeats in the instance document. Here’s fairly abstract example of schema definition that contains sequence group:
<xs:schemaxmlns:b="http://schemas.microsoft.com/BizTalk/2003"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="NS-Schema1"
           targetNamespace="NS-Schema1" >
 <xs:elementname="RepeatingSequenceGroups">
    <xs:complexType>
      <xs:sequencemaxOccurs="1"minOccurs="0">
        <xs:sequencemaxOccurs="unbounded">
          <xs:elementname="A"type="xs:string" />
          <xs:elementname="B"type="xs:string" />
          <xs:elementname="C"type="xs:string"minOccurs="0" />
        </xs:sequence>
      </xs:sequence>
    </xs:complexType>
 </xs:element>
</xs:schema>
And here’s corresponding XML instance document:
<ns0:RepeatingSequenceGroupsxmlns:ns0="NS-Schema1">
 <A>A1</A>
 <B>B1</B>
 <C>C1</C>
 <A>A2</A>
 <B>B2</B>
 <A>A3</A>
 <B>B3</B>
 <C>C3</C>
</ns0:RepeatingSequenceGroups>
As you can see elements A, B, and C are children of anonymous xs:sequence element which in turn can be repeated N times. Let’s say we need do simple mapping to the schema with similar structure but with different element names:
<ns0:Destinationxmlns:ns0="NS-Schema2">
 <Alpha>A1</Alpha>
 <Beta>B1</Beta>
 <Gamma>C1</Gamma>
 <Alpha>A2</Alpha>
 <Beta>B2</Beta>
 <Gamma>C2</Gamma>
</ns0:Destination>
The basic map for such typical task would look pretty straightforward:
If we test this map without any modification it will produce following result:
<ns0:Destinationxmlns:ns0="NS-Schema2">
 <Alpha>A1</Alpha>
 <Alpha>A2</Alpha>
 <Alpha>A3</Alpha>
 <Beta>B1</Beta>
 <Beta>B2</Beta>
 <Beta>B3</Beta>
 <Gamma>C1</Gamma>
 <Gamma>C3</Gamma>
</ns0:Destination>
The original order of the elements inside sequence is lost and that’s not what we want. Default behavior of the BizTalk 2009 and 2010 Map Editor is to generate compatible map with older versions that did not have ability to preserve sequence order. To enable this feature simply open map file (*.btm) in text/xml editor and find attribute PreserveSequenceOrder of the root <mapsource> element. Set its value to Yes and re-test the map:
<ns0:Destinationxmlns:ns0="NS-Schema2">
 <Alpha>A1</Alpha>
 <Beta>B1</Beta>
 <Gamma>C1</Gamma>
 <Alpha>A2</Alpha>
 <Beta>B2</Beta>
 <Alpha>A3</Alpha>
 <Beta>B3</Beta>
 <Gamma>C3</Gamma>
</ns0:Destination>
The result is as expected – all corresponding elements are in the same order as in the source document. Under the hood it is achieved by using one common xsl:for-each statement that pulls all elements in original order (rather than using individual for-each statement per element name in default mode) and xsl:if statements to test current element in the loop:
 <xsl:templatematch="/s0:RepeatingSequenceGroups">
    <ns0:Destination>
      <xsl:for-eachselect="A|B|C">
        <xsl:iftest="local-name()='A'">
          <Alpha>
            <xsl:value-ofselect="./text()" />
          </Alpha>
        </xsl:if>
        <xsl:iftest="local-name()='B'">
          <Beta>
            <xsl:value-ofselect="./text()" />
          </Beta>
        </xsl:if>
        <xsl:iftest="local-name()='C'">
          <Gamma>
            <xsl:value-ofselect="./text()" />
          </Gamma>
        </xsl:if>
      </xsl:for-each>
    </ns0:Destination>
 </xsl:template>
BizTalk Map editor became smarter so learn and use this lesser known feature of XSLT 2.0 in your maps and XSL stylesheets.

In my project I needed to separate template generated entities, context in separate projects from the EDMX file. I’ve stumbled across this problem how to make template generator to find edmx file without hardcoding absolute path into the template. Using relative path directly (inputFile=@”..\ProjectFolder\DataModel.edmx”) generated error:
 
Error      2              Running transformation: System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\ProjectFolder\DataModel.edmx'
 
The code that worked well for me when placed in the beginning of the .tt file:
 

string rootPath = Host.ResolvePath(String.Empty);
string relativePath = @"..\\ProjectDir\\DataModel.edmx";
string inputFile = Path.Combine(rootPath, relativePath);
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);

 
 

 


If you experience sequence of errors below with BizTalk HL7 MLLP receive ports you may need to request a hotfix from Microsoft. Knowledge base article number is 2454887 but it’s still not available on the KB site. The hotfix is recently released and you may need to open support ticket to get to it. It requires three other hotfixes installed:
·         970492 (DASM 3.7.502.2)
·         973909 (additional ACK codes)
·         981442 (Microsoft.solutions.btahl7.mllp.dll 3.7.509.2)
If the exceptions below repeatedly appear in the event log you most likely would be helped by the hotfix:
Fatal error encountered in 2XDasm. Exception information is Cannot access a disposed object. Object name: 'CEventingReadStream'.
There was a failure executing the receive pipeline: "BTAHL72XPipelines.BTAHL72XReceivePipeline, BTAHL72XPipelines, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Source: "BTAHL7 2.X Disassembler" Receive Port: "ReceivePortName" URI: "IPAddress:portNumber" Reason: Cannot access a disposed object. Object name: 'CEventingReadStream'.
The Messaging Engine received an error from transport adapter "MLLP" when notifying the adapter with the BatchComplete event. Reason "Object reference not set to an instance of an object."
We’ve been through a lot of troubleshooting with Microsoft Product Support and they did a great job finding an issue and releasing a fix.