Biztalk Mapping Question

Hi,

I have difficulty in mapping from source schema to target schema where my source schema  has a child record with a repeating element where Min occurs is 0 and max Occurs is 15. I have to map this element to the destination schema where it has a record "Name_Data" with Min occurs 1 and Max occurs 1. it has a child record "Name_Data" where Min occurs is 15 and max occurs is 15 which has a child element "Name" with min occurs 1 and max occurs1.

Requirement: Even In the input if I get only 3 repeating node values the out put of the destination map should have 15 values.I tried looping but i was only able to get 3 record values(As input has 3 repeating values) I need to assign Empty string to the rest for the 12 repeating values on the destination schema i.e on the whole I need to get 15 values in the output irrespective of input. I don't know how to assign values to rest of the records.

Sample destination schema
<ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>XYZ</ns0:Name>
      </ns0:Name_Data>
</ns0:Name_Data> can i achieve this using funtoids? or XSLT mapping

Thanks for you time!!!!

June 27th, 2013 7:20pm

KK

It would be lot easier if you can share your source and destination schamas along with sample input and desired output.

Free Windows Admin Tool Kit Click here and download it now
June 27th, 2013 8:13pm

SAAkhlaq,

Please find below for the sample input and output

Sample Input

<ns0:TransRequest xmlns:ns0="http://microsoft.com"">

  <ns0:In>

    <ns0:RecData>

        <ns0:Age>Age_0</ns0:Age>

        <ns0:FullName>FullName_0</ns0:FullName>

        <ns0:FullName>FullName_0</ns0:FullName>

        <ns0:FullName>FullName_0</ns0:FullName>

     </ns0:RecData>

   </ns0:In>

</ns0:TransRequest>

Expected Destination Output

<ns0:Request xmlns:ns0="http://microsoft.com"">
  <ns0:InDocument>
    <ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>Name_0</ns0:Name>
      </ns0:Name_Data>
    </ns0:Name_Data>
  </ns0:InDocument>
</ns0:Request>

June 27th, 2013 9:39pm

Hi KK,

Using Following input Schema

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns="http://microsoft.com" elementFormDefault="qualified" targetNamespace="http://microsoft.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="TransRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="In">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="RecData">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="Age" type="xs:string" />
                    <xs:element minOccurs="0" maxOccurs="15" name="FullName" type="xs:string" />
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

And following output schema:

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns="http://microsoft.com" elementFormDefault="qualified" targetNamespace="http://microsoft.com" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Request">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="InDocument">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Name_Data">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element minOccurs="15" maxOccurs="15" name="Name_Data">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="Name" type="xs:string" />
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

And using following map:

I am able to get following output:

<ns0:Request xmlns:ns0="http://microsoft.com">
  <ns0:InDocument>
    <ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>A</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>B</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>C</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>D</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>E</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>F</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>G</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>H</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>I</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>J</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>K</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>L</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>M</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>N</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>O</ns0:Name>
      </ns0:Name_Data>
    </ns0:Name_Data>
  </ns0:InDocument>
</ns0:Request>

for this input:

<ns0:TransRequest xmlns:ns0="http://microsoft.com">
  <ns0:In>
    <ns0:RecData>
      <ns0:Age>Age_0</ns0:Age>
      <ns0:FullName>A</ns0:FullName>
      <ns0:FullName>B</ns0:FullName>
      <ns0:FullName>C</ns0:FullName>
      <ns0:FullName>D</ns0:FullName>
      <ns0:FullName>E</ns0:FullName>
      <ns0:FullName>F</ns0:FullName>
      <ns0:FullName>G</ns0:FullName>
      <ns0:FullName>H</ns0:FullName>
      <ns0:FullName>I</ns0:FullName>
      <ns0:FullName>J</ns0:FullName>
      <ns0:FullName>K</ns0:FullName>
      <ns0:FullName>L</ns0:FullName>
      <ns0:FullName>M</ns0:FullName>
      <ns0:FullName>N</ns0:FullName>
      <ns0:FullName>O</ns0:FullName>
    </ns0:RecData>
  </ns0:In>
</ns0:TransRequest> 


Free Windows Admin Tool Kit Click here and download it now
June 27th, 2013 11:02pm

Thanks for your response.

But my input is below which has less than 15 repeating elements.

<ns0:TransRequest xmlns:ns0="http://microsoft.com">
  <ns0:In>
    <ns0:RecData>
      <ns0:Age>Age_0</ns0:Age>
      <ns0:FullName>A</ns0:FullName>
      <ns0:FullName>B</ns0:FullName>
      <ns0:FullName>C</ns0:FullName>
      <ns0:FullName>D</ns0:FullName>
      <ns0:FullName>E</ns0:FullName>
      <ns0:FullName>F</ns0:FullName>
    </ns0:RecData>
  </ns0:In>
</ns0:TransRequest>

And my output should be

<ns0:Request xmlns:ns0="http://microsoft.com">
  <ns0:InDocument>
    <ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>A</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>B</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>C</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>D</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>E</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name>F</ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name> </ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name> </ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name> </ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name> </ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name> </ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name> </ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name> </ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name> </ns0:Name>
      </ns0:Name_Data>
      <ns0:Name_Data>
        <ns0:Name> </ns0:Name>
      </ns0:Name_Data>
    </ns0:Name_Data>
  </ns0:InDocument>
</ns0:Request>


June 27th, 2013 11:13pm

You will have to use a custom XSL template.

For loops are tricky in XSLT but since 15 is a reasonable number, you can just define each one and use [position() = 1 -> 15] for the value.  For example:

<Name><xsl:value-of select="/FullName[position()=1]"/></Name>

<Name><xsl:value-of select="/FullName[position()=2]"/></Name>

...

<Name><xsl:value-of select="/FullName[position()=15]"/></Name>

However, position() returns the place in the current node set, so you may have to fiddle with the path a bit.

Free Windows Admin Tool Kit Click here and download it now
June 27th, 2013 11:28pm

Hi,

 Can you please try with the following xslt  and let me now if it works? Please change the namespaces of the input  and output in the below xslt before you use it . 

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:s0="http://MultiRepitNodeMap.Input" xmlns:ns0="http://MultiRepitNodeMap.Output" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
  <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
    <xsl:template match="/">
    <xsl:apply-templates select="/s0:Input" />
  </xsl:template>
  <xsl:template match="/s0:Input">
    <xsl:variable name="varCount" select="count(//Names/Name)" />
    <Name_Data>

      <xsl:for-each select="Names/Name">
        <Name_Data>
          <Name>
            <xsl:value-of select="./text()" />
          </Name>
        </Name_Data>
      </xsl:for-each>
      

        <xsl:variable name="emptyNodeCount" select="15 - ($varCount)" />
        <xsl:if test=" $emptyNodeCount !=0 ">
          <xsl:call-template name="Loop">
            <xsl:with-param name="emptyNodeCount">
              
            </xsl:with-param>
          </xsl:call-template>
        </xsl:if>

     
      </Name_Data>
    
    </xsl:template>
  <xsl:template name="Loop">
    <xsl:param name="emptyNodeCount"/>
    <Name_Data>
      <Name></Name>
    </Name_Data>
    <xsl:if test="$emptyNodeCount != 0">
    <xsl:call-template name="Loop">
      <xsl:with-param name="emptyNodeCount" select="$emptyNodeCount - 1">
      </xsl:with-param>
    </xsl:call-template>
    </xsl:if>
    </xsl:template>
    
  
  
  
  
</xsl:stylesheet>

June 27th, 2013 11:56pm

KK,

Please try following custom xsl:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:ns0="http://microsoft.com"
                exclude-result-prefixes="msxsl">
  
  <xsl:output method="xml" indent="no" omit-xml-declaration="yes"/>

  <xsl:template match="/">
    <xsl:element name="ns0:Request">
      <xsl:element name="ns0:InDocument">
        <xsl:element name="ns0:Name_Data">
          <xsl:call-template name="Loopable" />
        </xsl:element>
      </xsl:element>
    </xsl:element>
  </xsl:template>

  <xsl:template name="Loopable">
    <xsl:param name="index" select="1" />
    <xsl:param name="total" select="15" />

    <xsl:element name="ns0:Name_Data">
      <xsl:element name="ns0:Name">
        <xsl:value-of select="//ns0:TransRequest/ns0:In/ns0:RecData/ns0:FullName[$index]"/>
      </xsl:element>
    </xsl:element>
    
    <xsl:if test="not($index = $total)">
      <xsl:call-template name="Loopable">
        <xsl:with-param name="index" select="$index + 1" />
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
  
</xsl:stylesheet>

Free Windows Admin Tool Kit Click here and download it now
June 28th, 2013 7:45am

Hi Pmita,

Thanks for your response.

I tried the XSLT code that you provided but it generated the following output

<ns0:Request xmlns:ns0="http://microsoft.com"> - <InDocument> <Name_Data /> </InDocument> </ns0:Request>

June 28th, 2013 5:41pm

Hi,

     Please try the below xslt. I tested it . It is working as expected . Please mark this  post as answer if it works for you.

My Input

<s0:Input xmlns:s0="http://MultiRepitNodeMap.Input">
<Names>
  <Name>Name_0</Name> 
  <Name>Name_1</Name> 
  <Name>Name_2</Name> 
  </Names>
  </s0:Input>

XSLT

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var s0 userCSharp" version="1.0" xmlns:s0="http://MultiRepitNodeMap.Input" xmlns:ns1="http://MultiRepitNodeMap.Output" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp">
  <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
  <xsl:template match="/">
    <xsl:apply-templates select="/s0:Input/Names" />
  </xsl:template>
  <xsl:template match="/s0:Input/Names">
    <xsl:variable name="varCount" select="count(//Names/Name)" />
    <Name_Data>

      <xsl:for-each select="Name">
        <Name_Data>
          <Name>
            <xsl:value-of select="text()" />
          </Name>
        </Name_Data>
      </xsl:for-each>


      <xsl:variable name="emptyNodeCount" select="15 - ($varCount)" />
      
      <xsl:if test=" $emptyNodeCount !=0 ">
        <xsl:call-template name="Loop">
          <xsl:with-param name="NodeCount" select="$emptyNodeCount">

          </xsl:with-param>
        </xsl:call-template>
      </xsl:if>


    </Name_Data>

  </xsl:template>
  <xsl:template name="Loop">
    <xsl:param name="NodeCount"/>
    <Name_Data>
      <Name>
      </Name>
    </Name_Data>
    <xsl:if test="$NodeCount != 0">
      <xsl:call-template name="Loop">
        <xsl:with-param name="NodeCount" select="$NodeCount - 1">
        </xsl:with-param>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>





</xsl:stylesheet>

OUTPUT

<Name_Data xmlns:ns1="http://MultiRepitNodeMap.Output">
  <Name_Data><Name>Name_0</Name></Name_Data>
  <Name_Data><Name>Name_1</Name></Name_Data>
  <Name_Data><Name>Name_2</Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
  <Name_Data><Name></Name></Name_Data>
</Name_Data>


Free Windows Admin Tool Kit Click here and download it now
June 28th, 2013 6:59pm

Thank you all for your responses and for your Time.
It worked for me..
I have one more issue I need to call a template inside a template(as it had a loop inside a loop) so I am using two templates one inside another. When I do this I was not able to access [$index1] values in  <xsl:template name="LoopableAddress"> and if I give <xsl:param name="index1" select="1" /> this in LoopableAddress then it is always pointing to the first record values.
  How can i access   [$index1] in the other template as well?
  Below are my two sample templates.

  <xsl:template name="LoopableData">
  <xsl:param name="index1" select="1" />
  <xsl:param name="total1" select="6" />
  <xsl:element name="ns0:NAME_DATA">
    <xsl:element name ="ns0:NAME">
      <xsl:value-of select="//TransactionRequest/RecData/Data[$index1]/Name/text()"/>
    </xsl:element>
    <xsl:element name ="ns0:ADDRESS">
      <xsl:call-template name="LoopableAddress"></xsl:call-template>
    </xsl:element>
  </xsl:element>
  <xsl:if test="not($index1 = $total1)">
    <xsl:call-template name="LoopablePolData">
      <xsl:with-param name="index1" select="$index1 + 1" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

<xsl:template name="LoopableAddress">

<xsl:param name="index1" select="1" /> {it is always pointing to the first record values as it is creating a new param}

<xsl:param name="index" select="1" />
  <xsl:param name="total" select="15" />
  <xsl:element name="ns0:ADDRESS">
    <xsl:element name ="ns0:ADDRESS1">
      <xsl:value-of select="//TransactionRequest/RecData/Data[$index1]/Add[$index]/Address1/text()"/>
    </xsl:element>
    <xsl:element name ="ns0:ADDRESS2">
      <xsl:value-of select="//TransactionRequest/RecData/Data[$index1]/Add[$index]/Address2/text()"/>
    </xsl:element>
  </xsl:element>
  <xsl:if test="not($index = $total)">
    <xsl:call-template name="LoopableAddress">
      <xsl:with-param name="index" select="$index + 1" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

 
July 1st, 2013 10:28pm

by adding the below in my first template it solved the problem

<xsl:element name ="ns0:ADDRESS">
      <xsl:call-template name="LoopableAddress">
           <xsl:with-param name="index1" select="$index1" />
      </xsl:call-template>
</xsl:element>

Free Windows Admin Tool Kit Click here and download it now
July 2nd, 2013 10:46am

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics