将字符串的IObservable转换为XDocuments的IObservable

时间:2011-06-03 13:15:17

标签: c# system.reactive

我有一个包含(XML片段)文档的IObservable<string>。我想把一个变成另一个。例如,假设我有从我的IObservable<string>推送的以下片段(每行包含一个片段):

<?xml version=
"1.0" ?>
<testXml></test
Xml><?xml version="1.0"
?><otherXml /><?xm

如何将其转换为IObservable<XDocument>以获取以下文档:

<?xml version="1.0"?><testXml />
<?xml version="1.0"?><otherXml />

我一直在考虑将IObservable<string>移交给某些阻止TextReader实施,但我认为应该有一个更聪明的解决方案。

2 个答案:

答案 0 :(得分:4)

这个怎么样:

IObservable<string> splitXmlTokensIntoSeparateLines(string s)
{
    // Here, you need to split tokens into separate lines (where 'token'
    // is the beginning of an Xml element). This makes it easier down
    // the line for the TakeWhile operator.

    return new[] { firstPart, secondPart, etc }.ToObservable();
}

bool doesTokenTerminateDocument(string s)
{
    // Here, you should return whether the XML represents the end of one 
    // document
}

var xmlDocuments = stringObservable
    .SelectMany(x => splitXmlTokensIntoSeparateLines(x))
    .TakeWhile(x => doesTokenTerminateDocument(x))
    .Aggregate(new StringBuilder(), (acc, x), acc.Append(x))
    .Select(x => {
        var ret = new XDocument();
        ret.Parse(x.ToString());
        return ret;
    })
    .Repeat()
    .TakeUntil(stringObservable.Aggregate(0, (acc, _) => acc));

TakeUntil是一个让它正确终止的黑客 - 基本上,Repeat会继续重新订阅,除非我们在stringObservable完成时告诉它完成停止它。

答案 1 :(得分:0)

您无法使用Select运算符的任何原因?

var xmlObs = stringObs.Select(s => {
  var x = new XDocument();
  x.Parse(s);
  return x;
});