簡體   English   中英

在.NET3.5中處理格式錯誤的XML

[英]Processing badly formatted XML in .NET3.5

鑒於第三方系統通過TCP將XML流式傳輸給我。 TOTAL傳輸的XML內容(不是流的一條消息,而是連接的消息)如下所示:

   <root>
      <insert ....><remark>...</remark></insert>
      <delete ....><remark>...</remark></delete>
      <insert ....><remark>...</remark></insert>
      ....
      <insert ....><remark>...</remark></insert>
   </root>

上述樣品的每一行都是可單獨處理的。 由於它是一個流媒體流程,我不能等到一切都到來,我必須處理內容。 問題是內容塊可以被任何點切片,沒有標簽被尊重。 如果內容到達像這樣的片段,你對如何處理內容有什么好的建議嗎?

塊1:

  <root>
      <insert ....><rem

塊2:

                      ark>...</remark></insert>
      <delete ....><remark>...</remark></delete>
      <insert ....><remark>...</rema

塊N:

                                    rk></insert>
      ....
      <insert ....><remark>...</remark></insert>
   </root>

編輯:

雖然處理速度不是問題(沒有實時問題),但我不能等待整個消息。 實際上最后一塊大塊永遠不會到來。 第三方系統在遇到更改時發送消息。 這個過程永遠不會結束,它是一條永不停止的流。

我首先想到的是這個問題是創建一個簡單的TextReader派生物,它負責緩沖來自流的輸入。 然后,該類將用於提供XmlReader。 TextReader派生可以相當容易地掃描傳入的內容,尋找XML的完整“塊”(帶有開始和結束括號的完整元素,文本片段,完整屬性等)。 它還可以為調用代碼提供一個標志,以指示何時一個或多個“塊”可用,以便它可以從XmlReader請求下一個XML節點,這將觸發從TextReader派生中發送該塊並將其從緩沖區中刪除。

編輯:這是一個快速而骯臟的例子。 我不知道它是否完美(我還沒有測試過),但是它傳達了我想要傳達的想法。

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;
    }
}

經過進一步調查后,我們發現,只要XML緩沖區已滿,它就會被TCP緩沖區切片。 因此,切片實際上是在字節流中隨機發生的,甚至在unicode字符內也會導致切割。 因此,我們必須在字節級組裝部件並將其轉換回文本。 如果轉換失敗,我們等待下一個字節塊,然后再次嘗試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM