Managing Default Mapper Behavior Using <mapsource>

You can modify certain default behaviors of BizTalk Mapper by modifying attributes of the mapsource element directly in a map source (.btm) file.

Optimizing Value Mapping Functoid Code Generation

When the Mapper generates XSLT code to call the Value Mapping functoid, a variable is used to store the result. You can use the OptimizeValueMapping flag to optimize the Value Mapping functoid so that a variable is generated only when the if statement evaluates to True. For example, with OptimizeValueMapping set to No:

<xsl:variable name="var:v5" select="ScriptNS0:FormatMessage(…)" />  
<xsl:if test="string($var:v4)='true'">  
     <xsl:variable name="var:v6" select="string($var:v5)" />  
     <ns0:text>  
          <xsl:value-of select="$var:v6" />  
     </ns0:text>  
</xsl:if>  

This code could be optimized by moving the Value Mapping functoid invocation into the body of the if statement, ensuring that invocation occurs only when it is required. Setting OptimizeValueMapping to Yes yields the following code:

<xsl:if test="string($var:v4)='true'">  
     <xsl:variable name="var:v5" select="ScriptNS0:FormatMessage(…)" />  
     <xsl:variable name="var:v6" select="string($var:v5)" />  
     <ns0:text>  
          <xsl:value-of select="$var:v6" />  
     </ns0:text>  
</xsl:if>  

The Mapper does this optimization automatically if you set the OptimizeValueMapping attribute of the mapsource element in the map source (.btm) file to Yes as shown:

<mapsource Name="BizTalk Map" BizTalkServerMapperTool_Version="2.0" Version="2" XRange="100" YRange="420" OmitXmlDeclaration="Yes" TreatElementsAsRecords="No" OptimizeValueMapping="Yes" GenerateDefaultFixedNodes="Yes" CopyPIs="No" method="xml" xmlVersion="1.0" IgnoreNamespacesForLinks="Yes">  

Accommodating Schemas with Large Footprints

When the Mapper is using a schema that has a very large instance footprint with deep complex structures and/or recursive nodes, testing the map, validating the map, or compiling the map could take a long time or, in the worse case, result in an "out of memory" error. This could happen with small, complex schemas as well as with large schemas.

The problem with complex schemas is due to the fact that the Mapper has to recursively load the entire schema tree looking for nodes that either have links connected to them or have the Value property set on them. You can alleviate this problem by setting the GenerateDefaultFixedNodes flag of the mapsource element in the .btm files to No as shown:

<mapsource Name="BizTalk Map" BizTalkServerMapperTool_Version="2.0" Version="2" XRange="100" YRange="420" OmitXmlDeclaration="Yes" TreatElementsAsRecords="No" OptimizeValueMapping="No" GenerateDefaultFixedNodes="No" CopyPIs="No" method="xml" xmlVersion="1.0" IgnoreNamespacesForLinks="Yes">  

With this setting, the Mapper does not need to create internal compiler nodes associated with each schema node of a target schema. Only linked nodes are taken into account by the compiler. This significantly reduces the memory consumption and speeds up the process when doing a "test map" or "validate map" operation, compiling the map, or saving the map.

However, when the GenerateDefaultFixedNodes flag is set to No, the default field values set in the target schema are not preserved in the instance produced by the map. This is a problem when these values are required in the target instance. To circumvent this, the required values have to be set again explicitly in the map. You can set the GenerateDefaultFixedNodes flag to RequiredDefaults, which means that all required nodes are taken into account. This covers linked nodes, nodes that have default values, nodes with the MinOccurs property set to greater than or equal to one, and nodes whose parents are required.

Note

After you set GenerateDefaultFixedNodes to No or RequiredDefaults, you should test the map and verify that the output is the same as when GenerateDefaultFixedNodes is set to its default value of Yes, in which all nodes are taken into account by the compiler.

Managing for-each Usage with Looping, Conditional, and Value Mapping Functoids

When you use a Looping functoid, a Conditional functoid, or a Value Mapping functoid, an xsl:for-each statement is generated in the compiled map. If the child field of the destination schema has unbounded maximum occurrences, the xsl:for-each statement is put at the child field. If the child field does not have unbounded maximum occurrences, the xsl:for-each statement is put at the parent field of the child field.

However, because the location of the xsl:for-each statement affects the map result, you may want the xsl:for-each statement to be put at the child field of the destination schema, regardless of whether the maximum occurrence of the child field is set to 1.

You can control the placement of the xsl:for-each statement by modifying the value of the TreatElementsAsRecords attribute in the map (.btm) file as shown:

<mapsource Name="BizTalk Map" BizTalkServerMapperTool_Version="2.0" Version="2" XRange="100" YRange="420" OmitXmlDeclaration="Yes" TreatElementsAsRecords="No" OptimizeValueMapping="No" GenerateDefaultFixedNodes="Yes" CopyPIs="No" method="xml" xmlVersion="1.0" IgnoreNamespacesForLinks="Yes">  

When this attribute is set to Yes, the xsl:for-each statement is put at the child field of the destination schema, regardless of whether the maximum occurrence of the child field is set to 1.

Preserving the Order When Mapping a Repeating Sequence Group

Sequence groups in XSD schemas do not provide a looping context because they are not represented in the message instance. Without looping possibilities on the sequence group, the Mapper compiler does not generate the appropriate XSLT to maintain the segment order. As a result, relative context that is present in the input instance is lost, which makes the output instances useless for further processing that depends on the relative context.

You can use the PreserveSequenceOrder flag to maintain record order when mapping a repeating sequence to another repeating sequence. By default, the value of the flag is set to No to preserve the functionality of existing maps created in earlier BizTalk Server versions where the flag is not present. In the newly created maps, the flag will be present with its value set to No. To maintain segment order, you must explicitly set the value to Yes in the .btm files as shown:

<mapsource Name="BizTalk Map" BizTalkServerMapperTool_Version="2.0" Version="2" XRange="100" YRange="420" OmitXmlDeclaration="Yes" TreatElementsAsRecords="No" OptimizeValueMapping="No" GenerateDefaultFixedNodes="Yes" PreserveSequenceOrder="Yes" CopyPIs="No" method="xml" xmlVersion="1.0" IgnoreNamespacesForLinks="Yes">  

The following is a sample input instance:

<Name>Person1</Name>  
<Gender>Male</Gender>  
<Address>Bellevue</Address>  
<Name>Person2</Name>  
<Gender>Female</Gender>  
<Address>Redmond</Address>  

With the PreserveSequenceOrder flag set to No, the output instance will look like the following:

<Name>Person1</Name>  
<Name>Person2</Name>  
<Gender>Male</Gender>  
<Gender>Female</Gender>  
<Address>Bellevue</Address>  
<Address>Redmond</Address>  

With the PreserveSequenceOrder flag set to Yes, the output instance will look like the following:

<Name>Person1</Name>  
<Gender>Male</Gender>  
<Address>Bellevue</Address>  
<Name>Person2</Name>  
<Gender>Female</Gender>  
<Address>Redmond</Address>  

See Also

Creating Maps Using BizTalk Mapper