Creating a variable number of nodes on target document without corresponding data on source document

StackOverflow https://stackoverflow.com/questions/7493760

  •  24-01-2021
  •  | 
  •  

I'm trying to map two documents witht the BizTalk Mapper and my target document should look like this:

<root>
  <complexType>
     <property>example</property>
  </complexType>
  <filler>
     <padding>9999999</padding>
  </filler>
  <filler>
     <padding>9999999</padding>
  </filler>
  <filler>
     <padding>9999999</padding>
  </filler>
</root>

The number of <filler> nodes that I should create is variable (from 0 to 9). It is basically the result of a calculation (based on some data provided in the source document).

Is there a way to create those <filler> nodes with some combination of functoids?

I tried to use the Table Looping functoid (created a table with only one column, the padding char '9') but doesn't really work because it creates as many <filler> nodes as rows are defined in the table, which is not what I want since the number of rows would have to be variable (again, based on a calculation). What I currently do is pass the message (XmlDocument) to a C# method and then I programmatically append the <filler> nodes. I'm hoping that there is a more "BizTalk-y" way of doing this with the Mapper.

有帮助吗?

解决方案 2

As pointed out, XSLT can create nodes on the target document at will (I didn't know this and this was the key part). Turns out that what I needed is a simple for-loop in XSLT. Once I realized this, a quick Google search yielded the following results:

http://quomon.com/question-How-to-make-a-for-loop-in-xslt-not-for-each-809.aspx

http://snippets.dzone.com/posts/show/930

Another thing worth noting is that (as pointed out by the first link), XSLT is a functional language, not procedural, so sometimes you do have to resort to using recursion or an extension. This case is definitely one of those times since I couldn't use a careful selection of nodes using the select attribute on an xsl:for-each (since this filler data wasn't part of the source document).

Specifically, for this case, what I did was:

Add a Scripting functoid. Add two inputs:

  • A constant with value "1" (this is the initial value of the i variable)
  • The length of the loop (number of times to repeat the body of the loop)

Paste the following XSLT template as an "Inline XSLT Call Template" script:

<xsl:template name="ForLoop"> 
<xsl:param name="i" />      <!-- index counter, 1-based, will be incremented with every recursive call -->
<xsl:param name="length" /> <!-- exit loop when i >= length -->

<!-- Output the desired node(s) if we're still looping -->
<!-- The base case is when i > length (in that case, do nothing) -->
<xsl:if test="$i &lt;= $length"> 
<Filler>
    <Padding>999999</Padding>
</Filler>
</xsl:if> 

<!-- Call the ForLoop template recursively, incrementing i -->
<xsl:if test="$i &lt;= $length"> 
<xsl:call-template name="ForLoop"> 
<xsl:with-param name="i"> 
<xsl:value-of select="$i + 1"/> 
</xsl:with-param> 
<xsl:with-param name="length"> 
<xsl:value-of select="$length"/> 
</xsl:with-param> 
</xsl:call-template> 
</xsl:if> 
</xsl:template>

其他提示

I suspect that you will have to solve this problem by altering the XSLT.

Add some logic to create as many filler nodes as the result of your calculation dictates - you could create a template which you call in a loop perhaps, which would append a new filler section.

Hope this points you in the right direction.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top