是否放弃BizTalk平面文件处理中的任意头行?

是否放弃BizTalk平面文件处理中的任意头行?,biztalk,biztalk-schemas,Biztalk,Biztalk Schemas,我找到了这些相关的线索,但它们不能直接回答我的问题: 我正在处理一个旧的系统,它提供了一个非常松散的模式的平面文件。特别是,标题由两行组成:第一行是标题,第二行是列标题。所有后续行都是有效记录 问题是,当那天没有记录时,列标题被省略;在这种情况下,我们有文档标题,然后是一个摘要行(供人使用),通知读者当天没有记录 因为同一个文件可以有如此不同的格式,所以我很难创建一个可以在平面文件接收管道中使用的头模式,它允许我去掉头信息。此外,由于标题是多行的,因此我似乎不能只使用回车分隔符 我尝试了两种

我找到了这些相关的线索,但它们不能直接回答我的问题:

我正在处理一个旧的系统,它提供了一个非常松散的模式的平面文件。特别是,标题由两行组成:第一行是标题,第二行是列标题。所有后续行都是有效记录

问题是,当那天没有记录时,列标题被省略;在这种情况下,我们有文档标题,然后是一个摘要行(供人使用),通知读者当天没有记录

因为同一个文件可以有如此不同的格式,所以我很难创建一个可以在平面文件接收管道中使用的头模式,它允许我去掉头信息。此外,由于标题是多行的,因此我似乎不能只使用回车分隔符

我尝试了两种方法:

  • 包含两个回车分隔字段元素的标头架构,每个元素都是不透明字符串
  • 包含两个回车分隔记录的标头架构,每个记录定义一个虚拟中缀分隔符,该分隔符在任何一行中都不存在(导致每个记录有一个不透明字符串)
但是,当我部署这些文件时,BizTalk将拾取文件并对其进行处理,但实际上不会产生任何消息。这使我相信BizTalk将我的平面文件视为整个文件的头,因此它找不到任何记录

我试图找到的解决方案是如何创建一个头模式,使BizTalk将文件的前两行视为头,而不管其内容如何,并丢弃它们。这可能吗

编辑:不同文件的示例:

现有记录:

2017-02-27 19:27:03
CustomerName, OrderNumber, Expedite, ItemNumber, Count
CustomerA, O196801, 0, I232, 2
CustomerA, O196801, 0, I255, 1
CustomerB, O196802, 0, I237, 1
CustomerC, O196803, 0, I214, 1
CustomerC, O196803, 0, I232, 2
此文件中没有记录:

2017-02-27 19:30:22
***EOF***
  • 第一行总是相同的,可以用位置分隔的记录来描述
  • 第二行是以逗号分隔的列名列表,或者是这一行
  • 只有当没有记录时,EOF才会出现
目前,我只能通过将标题和文档架构之间的分隔符定义为整个列标题行来处理带有记录的文件,即
CustomerName、OrderNumber、accelerate、ItemNumber、Count{CR}{LF}

但是,当它找到的是
***EOF***
而不是列标题字符串时,此标题模式对空文件失败。

使用平面文件模式可能有一些聪明的方法来处理此问题,但我想不起来

我可能希望为管道编写一个自定义的
解码
组件,该组件将检查消息的前几个字节,以查找
***EOF***
——如果是这样,只需清空流(或者用预期的头文件重写它)——如果不是,则将流的位置重置回0并传递它

e、 g.(注:未测试,可能为工程代码):

public IBaseMessage Execute(ipipipelinecontext pContext,IBaseMessage pInMsg)
{
if(pInMsg==null | | pInMsg.BodyPart==null)返回pInMsg;
var stream=pInMsg.BodyPart.GetOriginalDataStream();
if(stream==null | | stream.Length==0)返回pInMsg;
if(!stream.CanSeek)
{
流=新的ReadOnlySeekableStream(流);
pContext.ResourceTracker.AddResource(流);
}
StreamReader=新的StreamReader(流);
pContext.ResourceTracker.AddResource(读卡器);
reader.ReadLine();//日期行
如果(reader.ReadLine()=“***EOF***”)
{
pInMsg.BodyPart.Data=null;
}
其他的
{
流位置=0;
pInMsg.BodyPart.Data=流;
}
返回pInMsg;
}

使用平面文件模式可能有一些聪明的方法来处理这个问题,但我想不出来

我可能希望为管道编写一个自定义的
解码
组件,该组件将检查消息的前几个字节,以查找
***EOF***
——如果是这样,只需清空流(或者用预期的头文件重写它)——如果不是,则将流的位置重置回0并传递它

e、 g.(注:未测试,可能为工程代码):

public IBaseMessage Execute(ipipipelinecontext pContext,IBaseMessage pInMsg)
{
if(pInMsg==null | | pInMsg.BodyPart==null)返回pInMsg;
var stream=pInMsg.BodyPart.GetOriginalDataStream();
if(stream==null | | stream.Length==0)返回pInMsg;
if(!stream.CanSeek)
{
流=新的ReadOnlySeekableStream(流);
pContext.ResourceTracker.AddResource(流);
}
StreamReader=新的StreamReader(流);
pContext.ResourceTracker.AddResource(读卡器);
reader.ReadLine();//日期行
如果(reader.ReadLine()=“***EOF***”)
{
pInMsg.BodyPart.Data=null;
}
其他的
{
流位置=0;
pInMsg.BodyPart.Data=流;
}
返回pInMsg;
}

您能给我们一些示例消息和您试图解决问题的示例模式吗?如果没有这些,就很难提供帮助。能否将第一个列名视为标记?如果是这样,你的问题听起来就没那么复杂了。@Dijkgraaf我加了一些例子!正如约翰所说。创建一个标记为CustomerName的记录,并使该记录的MinOccurs为0。对于您的数据,重复记录的最小值为0,另外一条记录的标记为EOF,最小值为0。@Dijkgraf我非常喜欢这个主意!然而,我不确定它是否能工作——当我尝试它时,BizTalk错误指出“无法匹配输入流中的数据”,并且它挂起的消息本身就是“EOF”。我的标题模式有日期行MinOccurs 1、列标题行、标记“CustomerName”MinOccurs 0和eof行标记“***eof”M