In this new mapping pattern, I want to show you how you can transform a hierarchical schema into a Name/Value Pair record.
📝 One-Minute Brief
This post provides a step-by-step tutorial on solving a common integration challenge: transforming data from a structured, hierarchical XML schema into a flattened Name-Value pair (Property/Value) structure. It demonstrates how to use the Looping, Table Looping, and Table Extractor functoids to iterate through nodes and map specific elements to a repetitive target structure, a pattern frequently used when interfacing with legacy systems or dynamic APIs.
The first thing we need to know is how I can read the name of the element from the source schema. By default, when we drag a link from the source to the destination schema, the value of the element is mapped to the destination schema, but we can change this behavior in the link properties by choosing “Copy name” in the “Source Links” property:
So to reach our goal, we need to link to the source to the destination schema:
- The link to the Name element is set with Copy name in the Source Links property.
- And the link to the Value element set with Copy text value (the default value) in the Source Links property.
Note: Before I start the solution to this problem, we need to notice that two elements are mapped directly:
- NProcesso to Id.
- and ServiceName to ServiceName.
And one element is not mapped, Tipo_Operacao. All other elements need to be mapped in the Name/Value Pair record.
First Solution: Using only Links
The first approach we think is to map all the elements using the method previously explained.
However, this approach has a problem because don’ the produce a valid message, instead of creating a record for each different element mapped, gathering all the Names and Values in a single record:
<ns0:Provisioning xmlns:ns0="http://SandroPereira.MappingToNameValueRecord.Provisioning">
<Id>Nprocesso_0</Id>
<Properties>
<Property>
<Name>IPRoute</Name>
<Name>Type</Name>
<Name>Protocol</Name>
<Name>Pool</Name>
<Name>VPNName</Name>
<Name>IPAddress</Name>
<Name>IPNetmask</Name>
<Name>Profile</Name>
<Name>VirtualRouter</Name>
<Name>IdleTimeout</Name>
<Name>SessionTimeout</Name>
<Name>TunnelType</Name>
<Value>IPRoute_0</Value>
<Value>Type_0</Value>
<Value>Protocol_0</Value>
<Value>Pool_0</Value>
<Value>VPNName_0</Value>
<Value>IPAddress_0</Value>
<Value>IPNetmask_0</Value>
<Value>Profile_0</Value>
<Value>VirtualRouter_0</Value>
<Value>IdleTimeout_0</Value>
<Value>SessionTimeout_0</Value>
<Value>TunnelType_0</Value>
</Property>
<ServiceName>ServiceName_0</ServiceName>
</ns0:Provisioning>
To solve this problem we need to add a Lopping functoid and map all the elements in this functoid:
Limitations of this approach:
- If the source schema has many elements, it takes much work to do this kind of mapping, and because we need many links to do this simple task, it may become difficult to read the map.
- We do not validate the existence of optional elements, which causes too many warnings.
- A new element in the source schema requires that we rectify the mapping.
Second Solution: Using only Links and validating the existence of optional elements
So, to avoid warnings of optional elements in the first approach, we need to use additional functoids. For each element mapped in the Name/Value Pair, we need to drag:
- One Logical Existence functoid and drag a link from the source element to this functoid
- And two Value Mapping functoids:
- Drag a link from the Logical Existence functoid to the first Value Mapping functoid.
- Drag a link from the Logical Existence functoid to the second Value Mapping functoid.
- Drag a link from the source element to the first Value Mapping functoid, and in the link properties, set with Copy name the Source Links property.
- Drag a link from the source element to the second Value Mapping functoid, and in the link properties, set with Copy text value the Source Links property.
- Drag a link from the first Value Mapping functoid to the element Name in the destination schema.
- Drag a link from the second Value Mapping functoid to the element Value in the destination schema.
Limitations of this approach:
- If the source schema has many elements, it takes much work to do this kind of mapping, and because we need many links and functoids to do this simple task, it may become difficult to read the map.
- A new element in the source schema requires that we rectify the mapping.
Third Solution: Using Inline XSLT
This is my favorite approach, and why? Because it basically solves all limitations of previous solutions: Too many tasks involved, too many links and functoids, and most importantly, it can be completely dynamic, i.e., if another element is added to the source schema, I don’t need to fix the mapping!
So, how can we accomplish this dynamic mapping?
We need to add to the grid two Scripting functoids:
- The first scripting functoid is to create a C# function to validate the existence of the element.
- In the scripting type, select Inline C# option
- In the Inline script, put the following code:
public string EmptyOrNull(string param)
{
if(string.IsNullOrEmpty(param))
return "false";
return "true";
}
- The second scripting functoid is for mapping all the elements in the Name/Value Pair
- In the scripting type, select Inline XSLT option.
- In the Inline script, put the following code:
<xsl:element name="Properties">
<xsl:for-each select="/s0:Request/Body/*">
<xsl:variable name="var:v2">
<xsl:value-of select="."/>
</xsl:variable>
<xsl:variable name="var:v1" select="userCSharp:EmptyOrNull(string($var:v2))" />
<xsl:if test="local-name()!='ServiceName' and local-name()!='LAN' and $var:v1='true'">
<xsl:element name="Property">
<xsl:element name="Name">
<xsl:value-of select="local-name()"/>
</xsl:element >
<xsl:element name="Value">
<xsl:value-of select="."/>
</xsl:element >
</xsl:element>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="/s0:Request/Body/LAN/*">
<xsl:variable name="var:v2">
<xsl:value-of select="."/>
</xsl:variable>
<xsl:variable name="var:v1" select="userCSharp:EmptyOrNull(string($var:v2))" />
<xsl:if test="$var:v1='true'">
<xsl:element name="Property">
<xsl:element name="Name">
<xsl:value-of select="local-name()"/>
</xsl:element >
<xsl:element name="Value">
<xsl:value-of select="."/>
</xsl:element >
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:element>
Finally, drag a link from the second scripting functoid to the Properties record in the destination schema:
Limitations of this approach:
- Because we use scripting functoids, we cannot read the entire map visually. We need to open the functoids and read, mainly, the XSLT code.
Fourth Solution: Using Table Looping functoid
Finally, I decided to create a fourth approach using the capabilities of the Table Looping functoid. For me, the big difference between this approach and the first two is that it is probably easier to read.
So instead of using the looping functoid and drag all links from the source directly to the destination schema, we will drag the links all the links from the source schema to the Table Looping functoid… but because you cannot drag to link from the same element to the Table Looping functoid (To map the name and the value) you need to use a workaround:
- Drag a Table Looping functoid to the map grid
- For each element, drag a String Concatenate functoid to the map grid
- Drag a link from the source element to the String Concatenate functoid and in the link properties, set with Copy name the Source Links property.
- Drag a link from the String Concatenate functoid to the Table Looping functoid and in the link properties, set the Label property to the following text <Element name> Name (note: you need to change <Element name> to the element concerned, ex, Type Name).
- Drag a link from the source element to the Table Looping functoid, and in the link properties, set with Copy text value the Source Links property.
In the Table Lopping functoid configuration, we need to set the first to inputs:
- The first is the number of elements mapped in the Table Lopping functoid.
- The second is the number of columns, in this case, 2.
And in the Table Lopping grid, we need to manually associate the first column with the name of the element, and in the second the value of the element:
Finally, we need to drag the Table Extractor functoid and configure it to read the first and the second column of the table:
Limitations of this approach:
- If the source schema has many elements, it takes much work to do this kind of mapping, and because we need many links and functoids to do this simple task, it may become difficult to read the map.
- We do not validate the existence of optional elements, which causes too many warnings.
- A new element in the source schema requires that we rectify the mapping
Download
THIS SOURCE CODE SCRIPT IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND.
You can download the source code used from GitHub here:
For those looking to move beyond the basics of message transformation, I highly recommend checking out my eBook, BizTalk Mapping Patterns & Best Practices, published in partnership with BizTalk360.
This resource is a deep dive into the real-world challenges of data transformation. It covers:
- Mapping Patterns: From simple field-to-field links to complex structural shifts.
- Performance Optimization: How to build maps that don’t slow down your environment.
- XSLT vs. Functoids: Knowing exactly when to use built-in tools and when to write custom code.
Whether you are maintaining a legacy BizTalk 2010 environment or planning a migration, these patterns are the foundation of clean, maintainable integration.
Download the full eBook here: BizTalk Mapping Patterns & Best Practices
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.









Very nice description of the various alternatives, Sandro. Thanks!
Great article. Just what I was looking for. Any advice on doing the reverse? Thanks
Hi Grant, this (the reverse) will be my next mapping post.