8

WCF プロジェクトで Rss20FeedFormatter クラスを使用しているときに、記述要素の内容を<![CDATA[ ]]>セクションでラップしようとしました。何をしても、description 要素の 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);
    }
}

... (次のコードは、Summary を 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 コード (私の知る限り、このロジックのため、上記のコードは機能しません)

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

この回避策のアイデアは、次の場所から来ました。MVC ではなく WCF で動作するように調整しました。http://localhost:8732/Design_Time_Addresses/SyndicationServiceLibrary1/Feed1/

これは単なる Rss20FeedFormatter のバグなのか、それとも仕様なのか? また、誰かがより良い解決策を持っているなら、私はそれを聞きたいです!

4

3 に答える 3

3

まあ@Page Brooks、私はこれを質問としてではなく解決策として見ています:)。ありがとう!!!そして、あなたの質問に答えるために ( ;) )、はい、これは間違いなく Rss20FeedFormatter のバグだと思います (私はそれを追跡しませんでしたが)、あなたが説明したのとまったく同じ問題に遭遇したからです。

投稿に「localhost:8732」の紹介がありますが、私のローカルホストでは利用できませんでした;)。「PostProcessOutputBuffer」の回避策をこの投稿にクレジットするつもりだったと思います: http://damieng.com/blog/2010/04/26/creating-rss-feeds-in-asp-net-mvc

または、実際にはこの投稿にはありませんが、David Whitney によるコメントにあり、後で別の要点をここに追加しました: https://gist.github.com/davidwhitney/1027181

私も回避策を見つけましたが、MVC からの適応にまだ苦労していたため、この回避策の適応を私のニーズに合わせて提供していただきありがとうございます。これで、使用していた .ashx ハンドラーの現在の Http 要求に RSS フィードを配置するために、ソリューションを微調整するだけで済みました。

基本的に、CDataSyndicationContent を使用して言及した修正は、2011 年 2 月のものであると推測しています (少なくとも私はそうしました): SyndicationFeed: Content as CDATA?

Rss20FeedFormatter のコードが投稿内容に変更されたため、この修正は新しい ASP.NET バージョンなどで機能しなくなりました。このコードの変更は、MVC フレームワークに含まれる他の機能の改善である可能性もありますが、CDataSyndicationContent 修正プログラムを使用している場合、間違いなくバグが発生します!

于 2013-05-23T22:31:40.803 に答える
1
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 は、cdataSections に単一の XmlQualifiedName "説明" が入力された XmlWriterSettings 型です。

それが他の誰かに役立つことを願っています。

于 2015-12-24T19:00:59.480 に答える