Rss20FeedFormatter Игнорирует тип TextSyndicationContent для SyndicationItem.Summary - PullRequest
8 голосов
/ 26 августа 2011

При использовании класса Rss20FeedFormatter в проекте WCF я пытался обернуть содержимое моих элементов описания разделом <![CDATA[ ]]>.Я обнаружил, что независимо от того, что я делал, содержимое HTML элементов описания всегда кодировалось, а раздел CDATA никогда не добавлялся.Вглядываясь в исходный код Rss20FeedFormatter, я обнаружил, что при построении узла Summary он в основном создает новый экземпляр TextSyndicationContent, который стирает все ранее заданные настройки ( Я думаю ).

Мой код

public class CDataSyndicationContent : TextSyndicationContent
{
    public CDataSyndicationContent(TextSyndicationContent content)
        : base(content)
    {
    }

    protected override void WriteContentsTo(System.Xml.XmlWriter writer)
    {
        writer.WriteCData(Text);
    }
}

... (следующий код должен обернуть резюме с разделом CDATA)

SyndicationItem item = new SyndicationItem();
item.Title = new TextSyndicationContent(name);
item.Summary = new CDataSyndicationContent(
                   new TextSyndicationContent(
                         "<div>This is a test</div>", 
                         TextSyndicationContentKind.Html));

Rss20FeedFormatter Code (AFAIK, приведенный выше код не работает из-за этой логики)

...
else if (reader.IsStartElement("description", ""))
   result.Summary = new TextSyndicationContent(reader.ReadElementString());
...

В качестве обходного пути я прибегнул к использованию RSS20FeedFormatter для созданияRSS, а затем исправьте RSS вручную.Например:

        StringBuilder buffer = new StringBuilder();
        XmlTextWriter writer = new XmlTextWriter(new StringWriter(buffer));
        feedFormatter.WriteTo(writer ); // feedFormatter = RSS20FeedFormatter

        PostProcessOutputBuffer(buffer);
        WebOperationContext.Current.OutgoingResponse.ContentType = 
                                   "application/xml; charset=utf-8";
        return new MemoryStream(Encoding.UTF8.GetBytes(buffer.ToString()));      

...

    public void PostProcessOutputBuffer(StringBuilder buffer)
    {
        var xmlDoc = XDocument.Parse(buffer.ToString());
        foreach (var element in xmlDoc.Descendants("channel").First()
                                      .Descendants("item")
                                      .Descendants("description"))
        {
            VerifyCdataHtmlEncoding(buffer, element);
        }

        foreach (var element in xmlDoc.Descendants("channel").First()
                                      .Descendants("description"))
        {
            VerifyCdataHtmlEncoding(buffer, element);
        }

        buffer.Replace(" xmlns:a10=\"http://www.w3.org/2005/Atom\"",
                       " xmlns:atom=\"http://www.w3.org/2005/Atom\"");
        buffer.Replace("a10:", "atom:");
    }

    private static void VerifyCdataHtmlEncoding(StringBuilder buffer,
                                                XElement element)
    {
        if (!element.Value.Contains("<") || !element.Value.Contains(">"))
        {
            return;
        }

        var cdataValue = string.Format("<{0}><![CDATA[{1}]]></{2}>",
                                       element.Name,
                                       element.Value, 
                                       element.Name);
        buffer.Replace(element.ToString(), cdataValue);
    }

Идея этого обходного пути возникла в следующем месте, я просто адаптировал его для работы с WCF вместо MVC.http://localhost:8732/Design_Time_Addresses/SyndicationServiceLibrary1/Feed1/

Мне просто интересно, является ли это просто ошибкой в ​​Rss20FeedFormatter или это задумано?Кроме того, если у кого-то есть лучшее решение, я бы хотел услышать его!

Ответы [ 3 ]

3 голосов
/ 24 мая 2013

Ну, @Page Brooks, я вижу это скорее как решение, чем как вопрос :).Спасибо!!!И чтобы ответить на ваш вопрос (;)), да, я определенно думаю, что это ошибка в Rss20FeedFormatter (хотя я не преследовал ее до сих пор), потому что столкнулся с точно такой же проблемой, которую вы описали.

У вас есть реферал localhost: 8732 в вашем посте, но он не был доступен на моем локальном хосте;).Я думаю, что вы имели в виду, что стоит отметить способ устранения 'PostProcessOutputBuffer' для этого поста: http://damieng.com/blog/2010/04/26/creating-rss-feeds-in-asp-net-mvc

Или на самом деле это не в этом посте, а в комментарии к нему Дэвида Уитни, который он позже поместил в отдельныйСуть здесь: https://gist.github.com/davidwhitney/1027181

Спасибо, что предоставили адаптацию этого обходного пути больше к моим потребностям, потому что я тоже нашел обходной путь, но все еще пытался сделать адаптацию от MVC.Теперь мне нужно только настроить ваше решение, чтобы поместить RSS-канал в текущий запрос Http в обработчике .ashx, в котором я его использовал.

По сути, я предполагаю, что исправление, которое вы упомянули с использованием CDataSyndicationContent,из февраля 2011 года, если вы получили его из этого поста (по крайней мере, я это сделал): SyndicationFeed: содержимое в виде CDATA?

Это исправление перестало работать в какой-то более новой версии ASP.NET или чем-то ещеиз-за изменения кода Rss20FeedFormatter в соответствии с тем, что вы указали в своем посте.Это изменение кода могло бы также быть улучшением для других вещей, которые есть в инфраструктуре MVC, но для тех, кто использует исправление CDataSyndicationContent, это определенно вызывает ошибку!

0 голосов
/ 24 декабря 2015
string stylesheet = @"<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform""><xsl:output cdata-section-elements=""description"" method=""xml"" indent=""yes""/></xsl:stylesheet>";
XmlReader reader = XmlReader.Create(new StringReader(stylesheet));
XslCompiledTransform t = new XslCompiledTransform(true);
t.Load(reader);

using (MemoryStream ms = new MemoryStream())
{
    XmlWriter writer = XmlWriter.Create(ms, t.OutputSettings);
    rssFeed.WriteTo(writer);  // rssFeed is Rss20FeedFormatter 
    writer.Flush();
    ms.Position = 0;
    string niko = Encoding.UTF8.GetString(ms.ToArray());
}

Я уверен, что кто-то уже указывал на это, но этот тупой обходной путь, который я использовал.t.OutputSettings относится к типу XmlWriterSettings, а cdataSections заполняется одним «описанием» XmlQualifiedName.

Надеюсь, что это поможет кому-то еще.

0 голосов
/ 18 августа 2015

Я нашел код для Cdata в другом месте

    public class CDataSyndicationContent : TextSyndicationContent
{
    public CDataSyndicationContent(TextSyndicationContent content)
        : base(content)
    {
    }

    protected override void WriteContentsTo(System.Xml.XmlWriter writer)
    {
        writer.WriteCData(Text);
    }
}

Код, чтобы назвать это что-то вроде:

item.Content = new Helpers.CDataSyndicationContent(new TextSyndicationContent("<span>TEST2</span>", TextSyndicationContentKind.Html));

Однако функция «WriteContentsTo» не вызывалась.

Вместо Rss20FeedFormatter я попробовал Atom10FeedFormatter - и это сработало! Очевидно, это дает канал Atom, а не традиционный RSS - но стоит упомянуть.

Код вывода:

//var formatter = new Rss20FeedFormatter(feed);
    Atom10FeedFormatter formatter = new Atom10FeedFormatter(feed);
    using (var writer = XmlWriter.Create(response.Output, new XmlWriterSettings { Indent = true }))
    {
        formatter.WriteTo(writer);
    }
...