在WCF项目中使用Rss20FeedFormatter类时,我试图用<![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代码 (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中的一个错误还是设计?此外,如果有人有更好的解决方案,我很乐意听到它!
答案 0 :(得分: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进行改编。现在我只需要调整你的解决方案,将RSS提要放在我使用它的.ashx处理程序中的当前Http请求中。
基本上我猜你使用CDataSyndicationContent提到的解决方案来自2011年2月,假设你从这篇帖子中得到它(至少我做过): SyndicationFeed: Content as CDATA?
由于Rss20FeedFormatter的代码更改为您在帖子中的内容,此修补程序停止在某些较新的ASP.NET版本中工作。这个代码更改可能也是对MVC框架中其他内容的改进,但对于那些使用CDataSyndicationContent修复的人来说肯定会导致错误!
答案 1 :(得分:0)
我在其他地方找到了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));
然而&#34; WriteContentsTo&#34;功能没有被调用。
我尝试使用Atom10FeedFormatter而不是Rss20FeedFormatter - 它有效! 显然,这给了Atom feed而不是传统的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);
}
答案 2 :(得分:0)
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“description”。
希望它可以帮助别人。