BizTalk Mapping循环问题:基于NumeroLinea值生成多行节点
解决BizTalk中根据NumeroLinea值生成对应数量节点的问题
老兄,我太懂你这种硬编码到崩溃的感受了——300多行的话,写内联XSLT functoid完全是自讨苦吃。其实用XSLT的递归模板就能轻松搞定这个需求,而且不管行数多少都能完美适配,还能保留输入输出的架构一致性。
核心思路
我们要做的就是:
- 保留原DDT节点里的所有其他内容(比如NumeroDDT、Date)
- 把原来单一的
<NumeroLinea>节点,替换成从1到原节点数值的所有<NumeroLinea>节点 - 用递归模板实现动态生成,避免硬编码上限
完整XSLT解决方案
直接用这段XSLT代码替换你原来的硬编码逻辑就行,不管NumeroLinea是2还是300都能正常工作:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 身份模板:默认复制所有节点和属性,保证原有结构不变 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 匹配原NumeroLinea节点,触发生成多节点逻辑 --> <xsl:template match="NumeroLinea"> <!-- 提取原节点的数值作为最大行数 --> <xsl:variable name="maxLineCount" select="number(.)"/> <!-- 调用递归模板生成行节点 --> <xsl:call-template name="GenerateLineNodes"> <xsl:with-param name="currentLine" select="1"/> <xsl:with-param name="maxLine" select="$maxLineCount"/> </xsl:call-template> </xsl:template> <!-- 递归生成行节点的模板 --> <xsl:template name="GenerateLineNodes"> <xsl:param name="currentLine"/> <xsl:param name="maxLine"/> <!-- 只要当前行数不超过最大值,就生成节点并递归 --> <xsl:if test="$currentLine <= $maxLine"> <NumeroLinea> <xsl:value-of select="$currentLine"/> </NumeroLinea> <!-- 递归调用,行数+1 --> <xsl:call-template name="GenerateLineNodes"> <xsl:with-param name="currentLine" select="$currentLine + 1"/> <xsl:with-param name="maxLine" select="$maxLine"/> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet>
代码解释
- 身份模板:这个模板是XSLT里的基础操作,会自动复制所有没有被特殊匹配的节点和属性,所以你的
NumeroDDT、Date这些节点都会原封不动保留下来。 - NumeroLinea匹配模板:专门捕获原有的
<NumeroLinea>节点,提取它的数值,然后调用递归模板开始生成节点。 - 递归生成模板:从1开始,每生成一个
<NumeroLinea>节点,就把当前行数加1,直到行数超过最大值为止,完美实现行计数器的功能。
在BizTalk中的使用方式
如果你用的是BizTalk Map:
- 可以直接在Map的属性里选择“Custom XSLT”,把这段代码粘贴进去
- 或者替换原来的内联XSLT functoid,用这段递归逻辑替代硬编码的分支
这个方案完全符合你输入输出架构一致的要求,而且没有行数上限,不管是2行还是300行都能轻松处理。
内容的提问来源于stack exchange,提问作者Rolf
相关产品推荐
相关产品推荐

