One of the more challenging things to do in XSL 1.0 was getting a distinct list of values from a set of nodes. There is no simple syntax for writing this type of XPath query. However, this is very easy to do in XSL 2.0:
<xsl:for-each select="distinct-values(…)">
But unfortunately, BizTalk does not support XSL 2.0.
In Sample 1, the transformation that needed to take place was to get the list of External Partners from a list of external employees.
<ns0:ExternalEmployees xmlns:ns0="http://SelectDistinctValues.Input">
<Employee>
<Name>Sandro Pereira</Name>
<Company>DevScope</Company>
</Employee>
<Employee>
<Name>Employee 1</Name>
<Company>DevScope</Company>
</Employee>
<Employee>
<Name>DemoEmployee2</Name>
<Company>DemoCompany2</Company>
</Employee>
<Employee>
<Name>Employee 2</Name>
<Company>DevScope</Company>
</Employee>
<Employee>
<Name>DemoEmployee</Name>
<Company>DemoCompany</Company>
</Employee>
</ns0:ExternalEmployees>
The first thing we need to do is to drag a Script functoid onto the Grid. Then, drag a line to the element we want to create output for.
We will start with the following XSLT to create the output in the format we want.
<xsl:variable name="unique-companies" select="//Employee[not(Company=preceding-sibling::Employee/Company)]/Company" />
This creates a variable named unique-companies and populates it with a list of unique companies nodes. Now, we need to start the output of our nodes and then loop through the companies. The following code will do that.
<xsl:for-each select="$unique-companies">
<PartnerName><xsl:value-of select="."/></PartnerName>
</xsl:for-each>
The output looks like this:
<ns0:ListPartners xmlns:ns0="http://SelectDistinctValues.Output1">
<PartnerName>DevScope</PartnerName>
<PartnerName>DemoCompany2</PartnerName>
<PartnerName>DemoCompany</PartnerName>
</ns0:ListPartners>
Sample 1 is composed by:
- Input.xsd and Output1.xsd
- Output1.xsd
- Input.xml
Sample 2 is a response to a question in the MSDN thread:
Giving data like this:
<Data Header="AAA" date="2008-10-28" Name="a1" Value="1.0" />
<Data Header="AAA" date="2008-10-28" Name="a2" Value="2.0" />
<Data Header="AAA" date="2008-10-28" Name="a3" Value="3.0" />
<Data Header="BBB" date="2008-10-28" Name="a1" Value="1.0" />
<Data Header="BBB" date="2008-10-28" Name="a2" Value="2.0" />
<Data Header="BBB" date="2008-10-28" Name="a3" Value="3.0" />
It was a requirement to map for the following schema format:
<data>
<header>AAA</header>
<date>2008-10-28</date>
<record>
<name>a1</name>
<value>1.0</value>
<name>a2</name>
<value>2.0</value>
<name>a3</name>
<value>3.0</value>
</record>
<header>BBB</header>
<date>2008-10-28</date>
<record>
<name>a1</name>
<value>1.0</value>
<name>a2</name>
<value>2.0</value>
<name>a3</name>
<value>3.0</value>
</record>
</data>
The logic is that you have to get the distinct values from Header, and then for all these distinct values select all element from this particular value, in this sample all element that has AAA in Header and then all BBB.
The map looks like this:
Basically, I use two functoid scripts with inline XSLT:
- In functoid 1, I created a template that gets all records for a specific Header sent by the parameter
<xsl:template name="NameValueTemplate">
<xsl:param name="param1" />
<xsl:for-each select="//Data[@Header=$param1]">
<xsl:element name="Name"><xsl:value-of select="@Name" /></xsl:element>
<xsl:element name="Value"><xsl:value-of select="@Value" /></xsl:element>
</xsl:for-each>
</xsl:template>
- In the functoid 2, I select all distinct Header and call a template for each header
<xsl:element name="Data">
<xsl:for-each select="Data[not(@Header=preceding-sibling::Data/@Header)]">
<xsl:element name="Header"><xsl:value-of select="@Header" /></xsl:element>
<xsl:element name="date"><xsl:value-of select="@date" /></xsl:element>
<xsl:element name="Record">
<xsl:call-template name="NameValueTemplate">
<xsl:with-param name="param1" select="string(@Header)" />
</xsl:call-template>
</xsl:element>
</xsl:for-each>
</xsl:element>
Sample 2 is composed by:
- DataInput.xsd and DataOutput.xsd
- DataMap.btm
- DataInput.xml
Source Code/Download
THIS COMPONENT IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND.
You can download the source code from GitHub here:
Hope you find this helpful! So, if you liked the content or found it useful and want to help me write more, you can help us buy a Star Wars Lego for my son!