丢弃BizTalk平面文件处理中的任意标题行?

时间:2017-02-24 18:45:37

标签: biztalk biztalk-schemas

我发现了这些相关主题,但他们没有直接回答我的问题:

BizTalk - Flat file with Header multiple records and Footer - Disassemble problem

Removing header from a flat file in BizTalk

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

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

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

我尝试了两种方法:

  • 包含两个回车符分隔的字段元素的标头架构,每个字段元素都是不透明的字符串
  • 包含两个回车分隔记录的标头架构,每个记录定义一个虚拟中缀分隔符,该分隔符在任一行中都不会存在(每个记录产生一个不透明的字符串)

然而,当我部署这些文件时,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 行。
  • EOF 仅在没有记录时出现。

目前我只能通过将标题和文档模式之间的分隔符定义为整个列标题行来处理带有记录的文件,即CustomerName, OrderNumber, Expedite, ItemNumber, Count{CR}{LF} 但是,当空文件找到***EOF***而不是列标题字符串时,此标头架构将失败。

1 个答案:

答案 0 :(得分:0)

使用Flat File架构可能有一些聪明的方法来解决这个问题,但我无法想到它。

我可能会为管道编写一个自定义Decode组件,它将检查该***EOF***的消息的前几个字节 - 如果是这样,只需将流清空(或者可能重写)它带有预期的标题) - 如果没有,将流的位置重置为0并将其传递。

e.g。 (注意:未经测试,可能是作品代码):

public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
{
    if (pInMsg == null || pInMsg.BodyPart == null) return pInMsg;

    var stream = pInMsg.BodyPart.GetOriginalDataStream();
    if (stream == null || stream.Length == 0) return pInMsg;

    if (!stream.CanSeek)
    {
        stream = new ReadOnlySeekableStream(stream);
        pContext.ResourceTracker.AddResource(stream);
    }

    StreamReader reader = new StreamReader(stream);
    pContext.ResourceTracker.AddResource(reader);
    reader.ReadLine(); // date line
    if (reader.ReadLine() == "***EOF***")
    {
        pInMsg.BodyPart.Data = null;
    }
    else 
    {
        stream.Position = 0;
        pInMsg.BodyPart.Data = stream;
    }
    return pInMsg;
}