BizTalk : How To : Map Repeating Sequence Elements

Friday, March 22, 2013
source: paul petrov


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:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns="NS-Schema1"
           targetNamespace="NS-Schema1" >
  <xs:element name="RepeatingSequenceGroups">
    <xs:complexType>
      <xs:sequence maxOccurs="1" minOccurs="0">
        <xs:sequence maxOccurs="unbounded">
          <xs:element name="A" type="xs:string" />
          <xs:element name="B" type="xs:string" />
          <xs:element name="C" type="xs:string" minOccurs="0" />
        </xs:sequence>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
And here's corresponding XML instance document:
<ns0:RepeatingSequenceGroups xmlns: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:Destination xmlns: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:Destination xmlns: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:Destination xmlns: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:template match="/s0:RepeatingSequenceGroups">
    <ns0:Destination>
      <xsl:for-each select="A|B|C">
        <xsl:if test="local-name()='A'">
          <Alpha>
            <xsl:value-of select="./text()" />
          </Alpha>
        </xsl:if>
        <xsl:if test="local-name()='B'">
          <Beta>
            <xsl:value-of select="./text()" />
          </Beta>
        </xsl:if>
        <xsl:if test="local-name()='C'">
          <Gamma>
            <xsl:value-of select="./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.

No comments:

Post a Comment

Post Your Comment...