BizTalk - 在编排中循环重复的消息节点
BizTalk - 在编排中循环重复的消息节点
假设你有一个包含许多重复节点的 BizTalk 入站消息,并且你想对每个节点执行相同的处理。最简单的方法是使用信封将单个消息拆分为多个消息,然后让编排的多个实例处理每个消息(类似于 HIPAA “多个”消息模式的工作方式)。但是,如果你需要在处理完每个单独的消息后执行一些操作怎么办?我将向你展示如何使用 Loop 形函数以及 xpath 查询来循环遍历消息。
在我的例子中,我正在接收一个平面文件,其中每一行都是对我们提交的事务的响应。在将平面文件映射到 XML 后,我得到如下内容
<Response> <Record> <RecordId>xxx</RecordId> <SubmitterId>xxx</SubmitterId> <Status>xxx</Status> </Record> <Record> <RecordId>xxx</RecordId> <SubmitterId>xxx</SubmitterId> <Status>xxx</Status> </Record> </Response>
我想将每个 Record 插入到数据库中,然后在所有 Record 都插入后执行一些操作。
第一步是创建消息的单个 Record 版本。它基本上与入站 Response 消息相同,只是缺少顶部的 Response 节点。
<Record> <RecordId>xxx</RecordId> <SubmitterId>xxx</SubmitterId> <Status>xxx</Status> </Record>
创建模式时不需要目标命名空间;稍后你就会明白原因。
接下来,创建编排,两个消息
- FullResponse(使用完整的平面文件模式)
- SingleResponse(使用新的单个 Record 模式)
…以及三个变量
- counter - int
- counterString – string
- responseCount - int
将各种形状拖到编排中,直到你得到如下所示的内容
我将从顶部开始,详细说明每个形状的配置方式。
Receive – 接收 FullResponse 消息
Expression - 在这里,你将使用 xpath 查询来计算 FullResponse 消息中 Record 节点的数量
responseCount = xpath(InstaMedResponse, "count(/*[local-name()='Response' and namespace-uri()='http://MyProject.Response_FF']/*[local-name()='Record' and namespace-uri()=''])"); counter = 1; counterString = "1";
(注意命名空间,你的可能不同)
Loop - 循环条件是什么?
counter <= responseCount
Message Assignment – 在这里,我们获取单个 Record 节点并将其分配给 SingleResponse 消息
SingleResponse = xpath(InstaMedResponse, "/*[local-name()='Response' and namespace-uri()='http://AnciPay.InstaMedResponse_FF']/*[local-name()='Record' and namespace-uri()=''][" + counterString + "]");
还记得我说新的模式需要创建时不带目标命名空间吗?你的 xpath 查询将返回不带命名空间的 Record 节点。此外,我们必须(不幸的是)使用 c
ounterString
而不是直接使用 counter.ToString()
,否则 BizTalk 会抱怨 xpath 错误。
Map – 这一个对于演示是可选的;在我的例子中,我将其映射到生成的模式的请求端。
Expression – 在这里,我们需要递增计数器
counter = counter + 1; counterString = counter.ToString();
Send & Receive - 我正在使用 WCF 端口保存到数据库,但如果你想,可以省略这些步骤。
Expression – 这可以是你在处理完每个单独的 Record 节点后想要发生的任何事情——运行存储过程、发送电子邮件,等等。
编译、部署和测试。如果你只是将 SingleResponse 消息放到发送端口(而不是数据库),你应该会看到你的入站消息被拆分为多个消息。