locked
BizTalk 2010 - Maps - Looping through repeating node for a single node output RRS feed

  • Question

  • Hi there,

    Here is my current map:

    If DepartmentHierarchyName and PayGroup match certain values, then I set a specific value to QualPos.

    Until now I had only 1 DepartmentHierarchyName and PayGroup and it was working fine:

    <ParentNode>
       ...
       <DepartmentHierarchyName>xxxxxx</DepartmentHierarchyName>
       <PayGroup>xxxxx</PayGroup>
       <PayGroupName>xxxxxx</PayGroupName>
    </ParentNode>

    But recently our source system has been updated and I'm now receiving multiple DepartmentHierarchyName:

    <ParentNode>
       ...
       <DepartmentHierarchyName>aaaaaa</DepartmentHierarchyName>
       <DepartmentHierarchyName>bbbbbb</DepartmentHierarchyName>
       <PayGroup>xxxxx</PayGroup>
       <PayGroupName>xxxxxx</PayGroupName>
    </ParentNode>

    So my map rule has to change to "If one of the DepartmentHierarchyName match the condition, then output the corresponding value to QualPos. (I don't want multiple QualPos node in the output).

    Is there a way I could achieve that with the standard functoid?

    Thanks

    Thursday, October 9, 2014 6:01 PM

Answers

  • Here is the Xslt I used and that seems to work:

    <xsl:template name="GetQualPos">
    <xsl:param name="IsOk" />
    
    	<xsl:for-each select="ParentNode1/ParentNode2/DepartmentHierarchyName">
    		<xsl:variable name="var:deptName" select="string(./text())" />
    		<xsl:if test="string($var:deptName)='aaaaa'">
    			<QualPos>FO</QualPos>
    		</xsl:if>
    		<xsl:if test="string($var:deptName)='bbbbb'">
    			<QualPos>RC</QualPos>
    		</xsl:if>
    		<xsl:if test="string($var:deptName)='cccccc'">
    			<QualPos>FA</QualPos>
    		</xsl:if>
    		<xsl:if test="(string($var:deptName)='ddddd') and (string($IsOk)='true')">
    			<QualPos>LE</QualPos>
    		</xsl:if>
    		<xsl:if test="(string($var:deptName)='eeeeee') and (string($IsOk)='false')">
    			<QualPos>UE</QualPos>
    		</xsl:if>
    	</xsl:for-each>
    
    </xsl:template>


    • Marked as answer by Jer-ome Wednesday, October 22, 2014 9:09 PM
    Wednesday, October 22, 2014 8:01 PM

All replies

  • You can achieve this by using "Equal"and "Value Mapping" functoids.

    Refer Approach1 (Using only functoids) of the article :- 

    http://social.technet.microsoft.com/wiki/contents/articles/20972.biztalk-server-how-to-map-values-from-a-repeating-node-into-a-single-node-using-conditions.aspx

    Rachit

    Please mark the post answered your question as answer, and mark other helpful posts as helpful, it'll help other users who are visiting your thread for the similar problem

    Thursday, October 9, 2014 6:10 PM
    Moderator
  • I'm not sure I can apply this solution. My problem is slightly different.

    In the link you sent me, imagine that the repeating node is the "Path" node, instead of "TimedValue", ie, the one you have to test in order to assign the output value.

    How would you then loop through it to check if one of them has the expecting value?

    Thursday, October 9, 2014 6:27 PM
  • Hi,

    I think you are better off writing custom inline XSLT using scripting functoid for this, should be simple.

    Let me know if you need any help doing that.

    Regards

    Pushpendra

    Thursday, October 9, 2014 7:40 PM
  • Hi Jerome,

    Yes, it works for the repeating record in source schema.

    lets say for example:

    <ParentNode>
       ...
       <DepartmentHierarchyName>aaaaaa</DepartmentHierarchyName>
       <DepartmentHierarchyName>bbbbbb</DepartmentHierarchyName>
       <PayGroup>xxxxx</PayGroup>
       <PayGroupName>xxxxxx</PayGroupName>
    </ParentNode>

    Your condition is to map DepartmentHierarchyName to destination field QualPos in case the value of DepartmentHierarchyName is 'aaaaaa'.

    Use Equal functoid and map the DepartmentHierarchyName to Equal functoid as input and the second input will be a value 'aaaaaa' and the output of the Equal functoid will be the first input to value mapping functoid and the second input will be the field DepartmentHierarchyName, the output will be then mapped to QualPos.

    The result will be like:-

    <ParentNode>
       ...
       <QualAc>xxxxxx</QualAc>
       <QualBase>xxxxxx</QualBase>
       <QualPos>aaaaaa</QualPos>
    </ParentNode>

    I hope this helps.

    When you say 'If one of the DepartmentHierarchyName match the condition', what condition you are referring to?

    Rachit



    Friday, October 10, 2014 5:18 AM
    Moderator
  • Hi,

    I think you are better off writing custom inline XSLT using scripting functoid for this, should be simple.

    Let me know if you need any help doing that.

    Regards

    Pushpendra

    Hi Pushpendra,

    Yes that was my second option but I was wondering if it would be possible only with functoids :)

    Friday, October 10, 2014 5:31 AM
  • Hi Rachit,

    What you are describing is pretty what is already done in my map (screenshot above).
    I have already five '=' functoids checking different values for DepartmentHierarchyName and linking the output of the equal to a value mapping functoid.
    One of the current rule is: if DepartmentHierarchyName = "Unlicensed Engineer" then assign "UE" to QualPos.

    And this doesn't work if the input Xml file has 2 or more DepartmentHierarchyName node. It seems that only the first one is being tested.

    I checked the Xslt generated; there is no loop on <ParentNode>, BizTalk is putting DepartmentHierarchyName in a variable:
    var:v15=string(.../DepartmentHierarchyName/text())
    This will get only the first DepartmentHierarchyName node. Then BizTalk simply apply the conditions to determine QualPos value.

    So I think I have no other choice than writing my own Xslt.

    Friday, October 10, 2014 6:10 AM
  • Hi ,

    Try to follow the below steps and let me know if it helps.

    1. Use looping functoid .Map DepartmentHierarchyName as input and attached output to QualPos.

    2. Now use = functoid and check whether the value is aaaaa. Attach the ouput to || (OR) functoid.

    3. If no , then use ! functoid and attach the output of = functoid previously used to this ! functoid.

    4. Then output of this ! functoid attach to value mapping functoid. Check whether the DepartmentHierarchyName  is bbbbb. Attach the output to previous || (OR) functoid.

    5. Finally use the output of || functoid to value mapping functoid to assign the values.

    Thanks,

    Tanmoy

    • Proposed as answer by Angie Xu Thursday, October 16, 2014 2:07 AM
    Friday, October 10, 2014 8:11 AM
  • Hi Tanmoy!

    Thank for your suggestion.

    I haven't had the chance to try it yet, my work priorities have shifted a little bit, but I will let you know as soon as start working on it again :)

    Jerome

    Thursday, October 16, 2014 2:16 AM
  • You could use inline xslt template in the scripting functoid and assign functoid output to the destination field.

    <xsl:for-each select="xpath of Parent node"> // loop through all the multiple accurnace

    <xsl:variable name= "dHN" select ="DepartmentHierarchyName/text()" />

    <xsl:if test =($dHN='aaaaaa')>// u can have multiple condition here with "and" seperated.

    <xsl : element name ="QualPos">

    <xsl:value-of select =" requiredvalue"/>

    </xsl:element>

    </xsl:if>

    <xsl:for-each>

    Thursday, October 16, 2014 2:45 AM
  • Hi

    @Tanmoy:

    I tried your solution, but unfortunately the looping functoid is not translated in Xslt as expected, so it's not working

    @Ismailgl:

    Your Xslt is interesting, but in my case the "Parent node" is not repeating, it's only the "DepartmentHierarchyName" that will repeat twice (not less, not more ... if the business requirement doesn't change again ;) )

    Wednesday, October 22, 2014 5:21 PM
  • Here is the Xslt I used and that seems to work:

    <xsl:template name="GetQualPos">
    <xsl:param name="IsOk" />
    
    	<xsl:for-each select="ParentNode1/ParentNode2/DepartmentHierarchyName">
    		<xsl:variable name="var:deptName" select="string(./text())" />
    		<xsl:if test="string($var:deptName)='aaaaa'">
    			<QualPos>FO</QualPos>
    		</xsl:if>
    		<xsl:if test="string($var:deptName)='bbbbb'">
    			<QualPos>RC</QualPos>
    		</xsl:if>
    		<xsl:if test="string($var:deptName)='cccccc'">
    			<QualPos>FA</QualPos>
    		</xsl:if>
    		<xsl:if test="(string($var:deptName)='ddddd') and (string($IsOk)='true')">
    			<QualPos>LE</QualPos>
    		</xsl:if>
    		<xsl:if test="(string($var:deptName)='eeeeee') and (string($IsOk)='false')">
    			<QualPos>UE</QualPos>
    		</xsl:if>
    	</xsl:for-each>
    
    </xsl:template>


    • Marked as answer by Jer-ome Wednesday, October 22, 2014 9:09 PM
    Wednesday, October 22, 2014 8:01 PM