【问题标题】:Creating a variable number of nodes on target document without corresponding data on source document在目标文档上创建可变数量的节点,而源文档上没有相应的数据
【发布时间】:2026-01-27 03:10:02
【问题描述】:

我正在尝试使用 BizTalk Mapper 映射两个文档,我的目标文档应如下所示:

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

我应该创建的&lt;filler&gt; 节点的数量是可变的(从 0 到 9)。它基本上是计算的结果(基于源文档中提供的一些数据)。

有没有一种方法可以使用一些 functoid 组合来创建那些 &lt;filler&gt; 节点?

我尝试使用 Table Looping functoid(创建了一个只有一列的表,填充字符 '9'),但它并没有真正起作用,因为它创建了与表中定义的行一样多的 &lt;filler&gt; 节点,这不是我想要的,因为行数必须是可变的(同样,基于计算)。 我目前所做的是将消息 (XmlDocument) 传递给 C# 方法,然后以编程方式附加 &lt;filler&gt; 节点。 我希望 Mapper 有一种更“BizTalk-y”的方式。

【问题讨论】:

    标签: xslt biztalk biztalk-mapper


    【解决方案1】:

    我怀疑您将不得不通过更改 XSLT 来解决这个问题。

    添加一些逻辑以根据计算结果创建尽可能多的填充节点 - 您可以创建一个模板,您可能会在循环中调用该模板,这将附加一个新的填充部分。

    希望这会为您指明正确的方向。

    【讨论】:

      【解决方案2】:

      正如所指出的,XSLT 可以随意在目标文档上创建节点(我不知道这一点,这是关键部分)。 事实证明,我需要的是 XSLT 中的一个简单的 for 循环。当我意识到这一点后,快速的 Google 搜索产生了以下结果:

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

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

      另一件值得注意的事情是(正如第一个链接所指出的),XSLT 是一种函数式语言,而不是过程式语言,因此有时您必须求助于递归或扩展。 这种情况肯定是其中一种情况,因为我无法使用 xsl:for-each 上的 select 属性仔细选择节点(因为此填充数据不是源文档的一部分)。

      具体来说,对于这种情况,我所做的是:

      添加一个脚本functoid。 添加两个输入:

      • 值为“1”的常量(这是 i 变量的初始值)
      • 循环的长度(循环主体的重复次数)

      将以下 XSLT 模板粘贴为“内联 XSLT 调用模板”脚本:

      <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>
      

      【讨论】:

      • 感谢您对 Q 的反馈 - 相信有一天会有用 :)
      最近更新 更多