首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在.NET3.5中处理格式错误的XML

在.NET3.5中处理格式错误的XML
EN

Stack Overflow用户
提问于 2011-06-23 13:41:29
回答 2查看 179关注 0票数 0

给出了一个第三方系统,该系统通过TCP将XML流给我。整个传输的XML内容(不是流的一条消息,而是连接的消息)如下所示:

代码语言:javascript
复制
   <root>
      <insert ....><remark>...</remark></insert>
      <delete ....><remark>...</remark></delete>
      <insert ....><remark>...</remark></insert>
      ....
      <insert ....><remark>...</remark></insert>
   </root>

上述样品的每一行都可单独处理。因为这是一个流的过程,我不能只是等待直到一切到来,我必须处理内容,因为它来了。问题是内容块可以被任何一点分割,没有标签被尊重。如果内容以这样的片段出现,你有什么好的建议吗?

第1组:

代码语言:javascript
复制
  <root>
      <insert ....><rem

第二部分:

代码语言:javascript
复制
                      ark>...</remark></insert>
      <delete ....><remark>...</remark></delete>
      <insert ....><remark>...</rema

块N:

代码语言:javascript
复制
                                    rk></insert>
      ....
      <insert ....><remark>...</remark></insert>
   </root>

编辑:

虽然处理速度不是问题(没有实时问题),但我不能等待整个消息。几乎最后一块都没到。第三方系统每当遇到更改时都会发送消息。这个过程永远不会结束,它是一个永不停止的流。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-29 08:10:42

经过进一步的研究,我们发现,当XML流满时,它已经被TCP缓冲区分割。因此,切片实际上是在字节流中随机进行的,甚至在unicode字符中也会导致切分。因此,我们必须在字节级别上组装这些部件,并将其转换回文本。如果会话失败,我们等待下一个字节块,然后再试一次。

票数 0
EN

Stack Overflow用户

发布于 2011-06-23 13:56:08

对于这个问题,我的第一个想法是创建一个简单的TextReader导数,它负责缓冲来自流的输入。然后,这个类将用于为XmlReader提供数据。TextReader派生程序可以相当容易地扫描传入的内容,寻找完整的XML“块”(一个包含开始和结束括号的完整元素、一个文本片段、一个完整的属性等等)。它还可以向调用代码提供一个标志,以指示何时有一个或多个“块”可用,以便它可以从XmlReader请求下一个XML节点,这将触发从TextReader派生程序发送该块并将其从缓冲区中删除。

编辑:下面是一个快速而肮脏的例子。我不知道它是否工作得很完美(我还没有测试它),但它让我明白了我想传达的想法。

代码语言:javascript
复制
public class StreamingXmlTextReader : TextReader
{
    private readonly Queue<string> _blocks = new Queue<string>();
    private string _buffer = String.Empty;
    private string _currentBlock = null;
    private int _currentPosition = 0;

    //Returns if there are blocks available and the XmlReader can go to the next XML node
    public bool AddFromStream(string content)
    {
        //Here is where we would can for simple blocks of XML
        //This simple chunking algorithm just uses a closing angle bracket
        //Not sure if/how well this will work in practice, but you get the idea
        _buffer = _buffer + content;
        int start = 0;
        int end = _buffer.IndexOf('>');
        while(end != -1)
        {
            _blocks.Enqueue(_buffer.Substring(start, end - start));
            start = end + 1;
            end = _buffer.IndexOf('>', start);
        }

        //Store the leftover if there is any
        _buffer = end < _buffer.Length
            ? _buffer.Substring(start, _buffer.Length - start) : String.Empty;

        return BlocksAvailable;
    }

    //Lets the caller know if any blocks are currently available, signaling the XmlReader can ask for another node
    public bool BlocksAvailable { get { return _blocks.Count > 0; } }

    public override int Read()
    {
        if (_currentBlock != null && _currentPosition < _currentBlock.Length - 1)
        {
            //Get the next character in this block
            return _currentBlock[_currentPosition++];
        }
        if(BlocksAvailable)
        {
            _currentBlock = _blocks.Dequeue();
            _currentPosition = 0;
            return _currentBlock[0];
        }
        return -1;
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6454997

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档