[英]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.