Scenario

This is a common scenario: An XML message is received and it contains a list of records that we want to split into multiple messages with one record each. 

I have seen many great articles about this. I've found this method to be the simplest, easiest and fastest. 

Solution

Creating an Envelope schema

The only artifact we will have to create to make this work is an Envelope schema. That is to say, a schema for the message that will be received that will contain the list of records we are looking at splitting. 

Using the regular XMLReceive pipeline to debatch your message

Using the XMLReceive pipeline on the receive location will cause the XMLDisassembler to identify your schema as an Envelope schema and trigger it to automatically debatch the original message. That means it will split the original message into multiple messages containing one record only. 

Implementation

We can start from the single record schema or from the multiple record schema. For this example we will start from the single record schema and create an Envelope schema from it. It is super quick and easy.

Here is what the single record schema we will use on this example looks like:

<?xml version="1.0" encoding="utf-16"?>
  <xs:element name="Product">
    <xs:complexType>
      <xs:attribute name="Symbol" type="xs:string" />
      <xs:attribute name="Description" type="xs:string" />
      <xs:attribute name="UOM" type="xs:string" />
    </xs:complexType>
  </xs:element>
</xs:schema>

Lets first create the Envelope schema and then configure it. Create a schema with a name that represents a collection of records. So if your record is called Product, add a schema to your project and name it Products. Rename the default element "Root" to the name of your schema. On this example we are naming it Products.

At this point your envelope schema will look something like this:

<?xml version="1.0" encoding="utf-16"?>
  <xs:element name="Products">
    <xs:complexType />
  </xs:element>
</xs:schema>

Select the <Schema> node on the schema editor and, on the properties window:
  1. Change the Envelope property to True.
  2. Click on the space beside Imports, click on the ellipsis, click Add and select the single record schema. On my example I selected ACME.BizTalkProject.Schemas.Product.
At this point your envelope schema will look something like this:

<?xml version="1.0" encoding="utf-16"?>
  <xs:import schemaLocation=".\Product.xsd" namespace="http://ACME.BizTalkProject.Schemas.Product" />
  <xs:annotation>
    <xs:appinfo>
      <b:schemaInfo is_envelope="yes" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" />
      <b:references>
        <b:reference targetNamespace="http://ACME.BizTalkProject.Schemas.Product" />
      </b:references>
    </xs:appinfo>
  </xs:annotation>
  <xs:element name="Products">
    <xs:complexType />
  </xs:element>
</xs:schema>

Select the element you renamed earlier. On my example I selected Products. On the properties window, click on the space beside Body XPath, click on the ellipsis, select the element you are configuring and click OK. That will bring the XPath to that element to the properties window line.

Right click on the element on the schema tree, select Insert Schema Node, select Child Record and hit Enter. Leave the default name on the element.

Select the newly added element and on the properties window:
  1. Click on the space beside Data Structure Type, click on the ellipsis and select  the root node from your single record schema from the drop down list.
  2. Enter unbounded on Max Occurs
The Envelope schema is ready to be used. It should be looking similar to this:

<?xml version="1.0" encoding="utf-16"?>
  <xs:import schemaLocation=".\Product.xsd" namespace="http://ACME.BizTalkProject.Schemas.Product" />
  <xs:annotation>
    <xs:appinfo>
      <b:schemaInfo is_envelope="yes" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" />
      <b:references>
        <b:reference targetNamespace="http://ACME.BizTalkProject.Schemas.Product" />
      </b:references>
    </xs:appinfo>
  </xs:annotation>
  <xs:element name="Products">
    <xs:annotation>
      <xs:appinfo>
        <b:recordInfo body_xpath="/*[local-name()='Products' and namespace-uri()='http://ACME.BizTalkProject.Schemas.Products']" />
      </xs:appinfo>
    </xs:annotation>
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" ref="ns0:Product" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Now the XMLDisassembler will know this is an Envelope schema when it looks it up on the BizTalk management database. It will also know which schema to use to debatch it.

Conclusion

You can create a smoke test harness with a receive and a send port using the FILE adapter , drop a message with multiple records in the inbound folder and watch multiple files appear in your outbound folder. 

See Also

Another important place to find an extensive amount of BizTalk related articles is the TechNet Wiki itself. The best entry point is BizTalk Server Resources on the TechNet Wiki.