BizTalk Map using custom XSLT

Problem

There is a requirement to generate output XML based on the attributes of input XML:

Following is my Input xml schema

InputSchema

And our output schema looks like below

outputschema

I have to map the “Property” and its attribute “Name” based on the values and name of the input schema “Branch” record. for each “Branch” in the input there should be one record of the “Location” in the output schema.

For example if below is our input XML :

inputxml

Then my output XML should be like below

outputxml

If you see in the output XML the property and its values are populated on the basis of incoming records in “Branch”.

Solution

I would do following to achieve this requirement, My favorite custom XSLT in BizTalk Maps:

It is very easy to generate a Custom XSLT, BizTalk Map generates the basic code for the schema namespace etc and then we can always modify it.

Steps:

  • Add a new MAP in the BizTalk project
  • Choose the input schema and output schema
  • after this the MAP should look like below:

Map1

  • start mapping the elements and records from input to output. So simple
  • We have to map the value of “Availability” to the value of “Property” and the “Name” attribute should be populated with “Availability” , So I would simply connect “Availability” to “Property” and use a concatenation functoid to assign the attribute “Name” to “Availability” . My map Will look something like below:

map2

  • Now I will generate my basic XSLT code which i will further modify. I will validate the MAP and after the validation I will get the basic XSLT which i will modify.
  • Right Click on the map in the solution explorer and Click “Validate” , Check the Visual Studio output window, there will be a message something like below

map3

  • Open the XSL file highlighted and save that in the BizTalk solution . Now we can modify this XSL file and use in our MAP.
  • to use the XSL file in our MAP we would need to delete all the links which we have done in the above steps and use the “Custom XSLT Path” property of the BizTalk MAP,
  • Delete all the links in the map
  • Open the MAP property and select the path of the XSL file which we have saved earlier.
  • After that my map looks like below:

map4

  • And we can now test the map using our Input.
  • The final XSLT looks like below, which does all the mapping.

<xsl:output omit-xml-declaration=”yes” method=”xml” version=”1.0″ />
<xsl:template match=”/”>
<xsl:apply-templates select=”/s0:QueryInput” />
</xsl:template>
<xsl:template match=”/s0:QueryInput”>
<ns0:QueryResponse>
<xsl:for-each select=”s0:Branch”>
<xsl:variable name=”var:v1″ select=”userCSharp:StringConcat(&quot;OnOrder&quot;)” />
<xsl:variable name=”var:v2″ select=”userCSharp:StringConcat(&quot;ETA&quot;)” />
<xsl:variable name=”var:v3″ select=”userCSharp:StringConcat(&quot;Availability&quot;)” />
<ns0:Location>
<ns0:Name>
<xsl:value-of select=”@Name” />
</ns0:Name>
<ns0:Quantity>
<xsl:value-of select=”s0:Availability/text()” />
</ns0:Quantity>
<ns0:Property>
<xsl:attribute name=”Name”>
<xsl:value-of select=”$var:v3″ />
</xsl:attribute>
<xsl:value-of select=”s0:Availability/text()” />
</ns0:Property>
<ns0:Property>
<xsl:attribute name=”Name”>
<xsl:value-of select=”$var:v1″ />
</xsl:attribute>
<xsl:value-of select=”s0:OnOrder/text()” />
</ns0:Property>
<ns0:Property>
<xsl:attribute name=”Name”>
<xsl:value-of select=”$var:v3″ />
</xsl:attribute>
<xsl:value-of select=”s0:ETA/text()” />
</ns0:Property>
<xsl:value-of select=”./text()” />
</ns0:Location>
</xsl:for-each>
</ns0:QueryResponse>
</xsl:template>
<msxsl:script language=”C#” implements-prefix=”userCSharp”><![CDATA[
public string StringConcat(string param0)
{
return param0;
}

]]></msxsl:script>
</xsl:stylesheet>

Hope it helps!

Thanks for reading!

BizTalk Schema to use <any> element

Overview

The XSD <any> element is very useful while designing generic schema or a schema to contain something unexpected/undefined or set of defined XML or elements.

The <any> element provides a way to keep/contain XML element which is not defined in the schema. For more details and example, Please read here :

Problem

There is a requirement to design a schema which should be generic in nature to contain any undefined type of XML. For example the following XML should be able to contain any XML in the <Details> element. As in the below example it contains <feedtext> element

schema input-1

The XM: should be able to contain any other XML in the <Details> as below a different input:

schema input-2

As in the above input XML , it contains <feedtextfromsite1>

Solution

To cater the above requirement we have to use <any> element in our schema . As defined in the page here, If a element is defined as <any> It can contain any other XML which is not defined in the schema.

Code

We will start by creating a schema using BizTalk Schema editor , Below are few steps:

  1. Create the Root Element and name it “MyBlogRssFeeds”
  2. Insert a  record and rename it to “Header”
  3. Insert a record below “Header”
  4. Insert a record below root element and name it “Details”
  5. Insert <any> element by Right Click on <Details>, then select “Insert Schema Node” then select “Any Element” .
  6. After this the schema should look like below:

Schema

And with this I was able to create a generic schema and was able to validate my XML.

And One More Thing!!

Please pay attention of the properties of <Any> element: It should look like below:

Schema Final

The property “Process Contents” should be set to “Skip” . Because of course we do not want the XML engine to validate the structure of this element.

the definition of this property is below from this page :

“Indicates how XML from other namespaces (introduced by the any element in a content model) should be validated. The value for this attribute may be one of ‘strict’ (the processor must retrieve the schema declaration associated with the namespace and validate the XML); ‘lax’ (the processor should attempt to validate the XML against its schema); and ‘skip’ (the processor should not attempt to validate the XML) “

Thanks for reading!