Basically, there are two properties inside the schema element that decide whether an element can be absent from the document: Min Occurs and Nillable.
If Min Occurs property is set 0 then that element can be absent from the XML message but if it is set to 1 it has to be present through its value can be empty. This is useful to reduce the size of the document if not all the elements are mandatory to end systems.
📝 One-Minute Brief
This post explains how BizTalk Mapper handles XML elements marked as nillable=”true” and why mappings may fail or produce unexpected results when the source element contains xsi:nil=”true”. The article demonstrates how BizTalk treats null XML values differently from empty nodes and shows how to correctly handle them using functoids and conditional logic to avoid unwanted output in transformed messages.
On the other hand, if the Nillable property of the element is set to true, this will indicate that the value of an element in the document may be null. These NULL values will be expressed with xsi:nil = true attribute in the element, ex:
<IntExist xsi:nil="true" />
An element with the attribute xsi:nil = true explicitly means that the value is unavailable or unknown at that moment, and sometimes the end system explicitly requires to be notified that the value of the element is NULL so that they can take appropriate action.
In this sample scenario, we will have 2 mandatory elements that can be nillable that we need to map to the destination schema. In this scenario, all the destination elements are also mandatory, and we need to fill them with a valid value or specify the nillable property as true: so if the element exists, we need to map the correct source value; otherwise, we need to set the destination element as nillable.
The first element, DateExist, is a mandatory element that can be null. If null, we need to set a null value in the destination element also as null; otherwise, we need to map the source value. To accomplish that, we need to:
- Drag one IsNil Functoid from the Toolbox window onto the Grid.
- Drag a link from the NilValue field element in the source schema to the IsNil Functoid
- Drag one Nil Value Functoid from the Toolbox window onto the Grid.
- Drag one Logical NOT Functoid from the Toolbox window onto the Grid.
- Drag one Value Mapping Functoid from the Toolbox window onto the Grid.
- To create a rule for mapping the value if the element is null
- Drag a link from the IsNil Functoid to the Nil Value Functoid
- Drag a link from the Nil Value Functoid to the NilValueOutput field element in the destination schema.
- Otherwise, To create a rule for mapping the value if the element is different from null:
- Drag a link from the IsNil Functoid to the Logical NOT Functoid.
- Drag a link from the Logical NOT Functoid to the Value Mapping Functoid Functoid.
- Drag a link from the NilValue field element in the source schema to the Value Mapping Functoid.
- Drag a link from the Value Mapping Functoid to the NilValueOutput field element in the destination schema.
Do the exact same logic for the second element present in the source schema.

Sometimes the maps are misunderstood and notorious for producing a lot of unnecessary code that may, in some cases, cause a lack of performance. So the question that we can and should ask is whether this is the best solution or not to address these types of operations. To respond to this question, we should also inspect the generated code produced by the BizTalk Mapper:
<xsl:variable name="var:v1" select="string(NillValue/@xsi:nil) = 'true'" />
<xsl:variable name="var:v2" select="userCSharp:LogicalNot(string($var:v1))" />
<xsl:variable name="var:v4" select="string(AnotherNilValue/@xsi:nil) = 'true'" />
<xsl:variable name="var:v5" select="userCSharp:LogicalNot(string($var:v4))" />
<ns0:OutputSchema>
<xsl:if test="string($var:v1)='true'">
<NillValueOutput>
<xsl:attribute name="xsi:nil">
<xsl:value-of select="'true'" />
</xsl:attribute>
</NillValueOutput>
</xsl:if>
<xsl:if test="string($var:v2)='true'">
<xsl:variable name="var:v3" select="NillValue/text()" />
<NillValueOutput>
<xsl:value-of select="$var:v3" />
</NillValueOutput>
</xsl:if>
<xsl:if test="string($var:v4)='true'">
<AnotherNilValueOutput>
<xsl:attribute name="xsi:nil">
<xsl:value-of select="'true'" />
</xsl:attribute>
</AnotherNilValueOutput>
</xsl:if>
<xsl:if test="string($var:v5)='true'">
<xsl:variable name="var:v6" select="AnotherNilValue/text()" />
<AnotherNilValueOutput>
<xsl:value-of select="$var:v6" />
</AnotherNilValueOutput>
</xsl:if>
</ns0:OutputSchema>
</xsl:template>
In fact, is a pretty decent XSLT code but the reality is that it can be better, we don’t need to use any support variables and we can remove one if condition by replacing the xsl:if condition for one xsl:choose condition.
This is a very simple approach, easy to implement, and readable, which you should use even in small or large messages (transformations), but only if you have to deal with a small number of nullable elements.
However, applying this approach in a transformation that will need to deal with a large number of nillable elements, can lead to two problems:
- A lot of unnecessary XSLT code that can, in fact, and of course, always, depending on the size of the message, lead to some lack of performance.
- A lot of functoid shapes (4 Functoids) and links (7 links) for each element, which can lead to a lack of visual Readability.
So, can we improve this solution for transformations that need to deal with a large number of nullable elements?
Well, that’s the problem, there isn’t a simple solution for that. At first glance, you may think that’s easy, just copy the XSLT code inside to a Scripting Functoid and optimize the XSLT code.
However, by doing that, you will receive an error:
error btm1050: XSL transform error: Unable to write output instance to the following <file:///C:\…\MapNillValuesWithCustomXSLT_output.xml>. Prefix ‘xsi’ is not defined.
The problem is that the nil attribute is defined in the XML Schema instance namespace, http://www.w3.org/2001/XMLSchema-instance (commonly associated with the prefix xsi), and this namespace is not declared by default in the XSL code generated by the BizTalk Mapper.
This namespace is automatically declared only if you use the Nil Functoids in the map.
So the normal solution here is… to bypass the BizTalk Mapper and generate an external XSLT code and add it to the map by specifying the Custom XSLT Path by:
- Open the map
- Click the grid zone, and in the properties window, there will be a Custom XSLT Path property. Click the ellipses and navigate to the file containing the XSLT.
You can then use a similar code to check and map the elements:
<xsl:choose>
<xsl:when test="NillValue/@xsi:nil">
<NillValueOutput>
<xsl:attribute name="xsi:nil">
<xsl:value-of select="'true'" />
</xsl:attribute>
</NillValueOutput>
</xsl:when>
<xsl:otherwise>
<NillValueOutput>
<xsl:value-of select="NillValue/text()" />
</NillValueOutput>
</xsl:otherwise>
</xsl:choose>
However, applying this approach, we have a major problem for me:
- We lose all the BizTalk Mapper functionalities.
Workaround
Well, at least that I know, unfortunately, there is no simple way to declare the xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance namespace to the stylesheet of the map.
However, we can apply one small workaround, which is not perfect, but in most cases it will solve my problems:
- For only one of the nillable elements we need to use the Nil Functoids explained at the beginning of this post.
- This will declare automatically the name xsi namespace for us.
- In the rest of the elements, we can now use Scripting Functoids with the optimized XSLT code described above.
I’m still working to find a better way, but until then…
Download
THIS SAMPLE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND.
You can download BizTalk Mapper: Working With Nillable Values (xsi:nil=”true”) from GitHub here:
Hope you find this helpful! If you liked the content or found it useful and would like to support me in writing more, consider buying (or helping to buy) a Star Wars Lego set for my son.


Add the namespace to the attribute
xsl:attribute name=”xsi:nil” namespace=”xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance”
Hi Fernando,
I try that solution but when I test the map it will generate an error btm1050: XSL transform error: Unable to write output instance to the following… Prefix ‘xsi’ is not defined.
If you own/control either the source or the target schema then just add the namespace there. it will then be added to the map in the imports section.
Reblogged this on Dinesh Ram Kali..
sorry the declaration must be namespace=”http://www.w3.org/2001/XMLSchema-instance” not namespace=”xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance”