Looping over a scripting functoid in BizTalk

2019-08-27 09:29发布

问题:

I've got a list of string values like '123','456','789' and so on. This list can be very long with a few thousand items. So I have to split it in blocks of max. 750 items.
One idea is to write an own functoid which split in and returns a loopable list. Maybe it is a little bit easier and i could do it direcly in a scripting functoid. But I get the message

`error btm1090: The "Looping" functoid has place holders. Replace these with appropriate links or constants.`



So I don't think that this is possible. Is there a possibility to do it in a Scripting functoid or do I need my own functoid?

I need the splitted values on the one hand to create multiple results lines (by looping) but also the value itself in each line.

Thanks in advance.

回答1:

Using Inline XSLT Call Template in Scripting functoids you could do something like this.

Functoid 1 (stand-alone):

<xsl:template name="SplitValues">
  <xsl:param name="value" />

  <xsl:variable name="part" select="substring-before($value, ',')" />

  <xsl:if test="$part != ''">
    <v><xsl:value-of select="$part" /></v>

    <xsl:call-template name="SplitValues">
      <xsl:with-param name="value" select="substring-after($value, ',')" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

Functoid 2:

  <xsl:variable name="split">
    <xsl:call-template name="SplitValues">
      <xsl:with-param name="value" select="$value" />
    </xsl:call-template>
  </xsl:variable>

  <xsl:variable name="set" select="msxsl:node-set($split)" />
  <xsl:variable name="size" select="750" />

  <xsl:for-each select="$set/v[position() mod $size = 1]">
    <xsl:variable name="start" select="(position() - 1) * $size + 1" />

    <LineValue>
      <xsl:value-of select="text()" />

      <xsl:for-each select="$set/v[position() &gt; $start and position() &lt; $start + $size]">
        <xsl:text>,</xsl:text>
        <xsl:value-of select="text()" />
      </xsl:for-each>
    </LineValue>
  </xsl:for-each>
</xsl:template>

Input[0]: the '123','456','789' node



回答2:

I would use a different approach. Instead of trying to do a restricted loop in Xsl, which is hard, I would generate all the Xml in a C# function, which is pretty easy.

Step 1, write some C# that create the Xml output you need:

<LineValue>'1','2','3',...,'749','750'</LineValue>
<LineValue>'751','752','753',...,'1499','1500'</LineValue>
<LineValue>'1501','1502','1503',...,'2249','2250'</LineValue>

An External Assembly is generally preferred but inline works just as well. But, it really doesn't matter, just return this Xml as a string.

Step 2, the only 'trick' you need is to pass the C# output through a Xslt Template so it's treated as Xml, not String content.

<xsl:template name="MyXsltConcatTemplate">
     <xsl:param name="param1" />
     <xsl:element name="field">
          <xsl:value-of select="$param1" disable-output-escaping="yes" />
     </xsl:element>
</xsl:template>

disable-output-escaping="yes" is what makes this work.