Преобразуйте IObservable строк в IObservable из XDocuments - PullRequest
2 голосов
/ 03 июня 2011

У меня есть IObservable<string>, который содержит (фрагменты) XML-документов.Я хотел бы превратить одно в другое.Например, предположим, что у меня есть следующие фрагменты, которые выдвинуты из моего 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 ]

4 голосов
/ 03 июня 2011

Как насчет этого:

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 завершит работу.

0 голосов
/ 03 июня 2011

Есть ли причина, по которой вы не можете использовать оператор Select?

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