Reputation: 111
I'm trying to serialize some c# classes to xml for an RSS feed. I have one remaining issue, the thumbnail element needs media as a namespace and I've been unable to figure out how to add it correctly. Right now I have it working with a string replace but I would rather do it the right way. I don't think it matters but i'm working with Umbraco.
What my code currently generates:
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0">
<channel>
<title>blog.example.com</title>
<link>http://blog.example.com/</link>
<description />
<item>
<title>Fake Post 1</title>
<link>http://www.example.com/post-1</link>
<description />
<pubDate>Thu, 25 Sep 2014 07:38:15 GMT</pubDate>
<guid isPermaLink="false">http://www.example.com/post-1</guid>
<media_x003A_thumbnail url="http://www.example.com/post-1/1.png" width="9001" height="9001" />
</item>
<item>
<title>Fake Post 2</title>
<link>http://www.example.com/post-2</link>
<description />
<pubDate>Thu, 25 Sep 2014 07:38:15 GMT</pubDate>
<guid isPermaLink="false">http://www.example.com/post-2</guid>
<media_x003A_thumbnail url="http://www.example.com/post-2/2.png" width="9001" height="9001" />
</item>
</channel>
</rss>
What I want my code to generate:
<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:media="http://search.yahoo.com/mrss" version="2.0">
<channel>
<title>blog.example.com</title>
<link>http://blog.example.com/</link>
<description />
<item>
<title>Fake Post 1</title>
<link>http://www.example.com/post-1</link>
<description />
<pubDate>Thu, 25 Sep 2014 07:38:15 GMT</pubDate>
<guid isPermaLink="false">http://www.example.com/post-1</guid>
<media:thumbnail url="http://www.example.com/post-1/1.png" width="9001" height="9001" />
</item>
<item>
<title>Fake Post 2</title>
<link>http://www.example.com/post-2</link>
<description />
<pubDate>Thu, 25 Sep 2014 07:38:15 GMT</pubDate>
<guid isPermaLink="false">http://www.example.com/post-2</guid>
<media:thumbnail url="http://www.example.com/post-2/2.png" width="9001" height="9001" />
</item>
</channel>
</rss>
c# classes (originally generated using "paste as xml classes" but I had to modify it a bit:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Web;
using System.Xml;
using System.Xml.Serialization;
/// <remarks/>
[XmlRoot("rss")]
[XmlTypeAttribute(AnonymousType = true)]
public partial class rss {
private rssChannel channelField;
private string versionField;
private string mediaField;
/// <remarks/>
public rssChannel channel {
get {
return this.channelField;
}
set {
this.channelField = value;
}
}
/// <remarks/>
[XmlAttributeAttribute()]
public string version {
get {
return this.versionField;
}
set {
this.versionField = value;
}
}
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces xmlns;
}
/// <remarks/>
[XmlTypeAttribute(AnonymousType = true)]
public partial class rssChannel {
private string titleField;
private string linkField;
private string descriptionField;
private rssChannelItem[] itemField;
/// <remarks/>
public string title {
get {
return this.titleField;
}
set {
this.titleField = value;
}
}
/// <remarks/>
public string link {
get {
return this.linkField;
}
set {
this.linkField = value;
}
}
/// <remarks/>
public string description {
get {
return this.descriptionField;
}
set {
this.descriptionField = value;
}
}
/// <remarks/>
[XmlElementAttribute("item")]
public rssChannelItem[] item {
get {
return this.itemField;
}
set {
this.itemField = value;
}
}
}
/// <remarks/>
[XmlTypeAttribute(AnonymousType = true)]
public partial class rssChannelItem {
private string titleField;
private string linkField;
private string descriptionField;
private string pubDateField;
private rssChannelItemGuid guidField;
private rssChanelItemMediaThumbnail mediaThumbnailField;
/// <remarks/>
public string title {
get {
return this.titleField;
}
set {
this.titleField = value;
}
}
/// <remarks/>
public string link {
get {
return this.linkField;
}
set {
this.linkField = value;
}
}
/// <remarks/>
public string description {
get {
return this.descriptionField;
}
set {
this.descriptionField = value;
}
}
/// <remarks/>
public string pubDate {
get {
return this.pubDateField;
}
set {
this.pubDateField = value;
}
}
/// <remarks/>
public rssChannelItemGuid guid {
get {
return this.guidField;
}
set {
this.guidField = value;
}
}
//hack TODO fix
[XmlElement(ElementName = "media:thumbnail")]
public rssChanelItemMediaThumbnail mediaThumbnail {
get {
return this.mediaThumbnailField;
}
set {
this.mediaThumbnailField = value;
}
}
}
/// <remarks/>
[XmlTypeAttribute(AnonymousType = true)]
public partial class rssChannelItemGuid {
private bool isPermaLinkField;
private string valueField;
/// <remarks/>
[XmlAttributeAttribute()]
public bool isPermaLink {
get {
return this.isPermaLinkField;
}
set {
this.isPermaLinkField = value;
}
}
/// <remarks/>
[XmlTextAttribute()]
public string Value {
get {
return this.valueField;
}
set {
this.valueField = value;
}
}
}
[XmlTypeAttribute(AnonymousType = true)]
public partial class rssChanelItemMediaThumbnail {
private string urlField;
private string widthField;
private string heightField;
/// <remarks/>
[XmlAttributeAttribute()]
public string url {
get {
return this.urlField;
}
set {
this.urlField = value;
}
}
/// <remarks/>
[XmlAttributeAttribute()]
public string width {
get {
return this.widthField;
}
set {
this.widthField = value;
}
}
/// <remarks/>
[XmlAttributeAttribute()]
public string height {
get {
return this.heightField;
}
set {
this.heightField = value;
}
}
}
functions that build the xml:
/// <summary>
/// Create a BlogRssFeedModel
/// </summary>
/// <param name="content"></param>
/// <param name="culture"></param>
/// <returns></returns>
public static BlogRssFeedModel CreateBlogRssFeedModel(IPublishedContent content, CultureInfo culture) {
IPublishedContent blogHomePage = content.AncestorsOrSelf(1).FirstOrDefault();
BlogRssFeedModel blogRssFeedModel = new BlogRssFeedModel(content, culture);
List<String> validDocumentTypes = new List<String>() { "BlogEntry" };
List<IPublishedContent> blogPosts = blogHomePage.Descendants().Where(x => validDocumentTypes.Contains(x.DocumentTypeAlias)).OrderByDescending(x => x.GetPropertyValue<DateTime>("sortDate")).ToList();
rss blogRssFeed = new rss();
blogRssFeed.version = "2.0";
blogRssFeed.xmlns = new XmlSerializerNamespaces();
blogRssFeed.xmlns.Add("media", "http://search.yahoo.com/mrss");
blogRssFeed.channel = new rssChannel();
blogRssFeed.channel.title = blogHomePage.Name;
blogRssFeed.channel.description = blogHomePage.GetPropertyValue<string>("pageDescription");
blogRssFeed.channel.link = blogHomePage.Url;
blogRssFeed.channel.item = blogPosts.Select(x => CreateRssChannelItem(x)).ToArray();
//some (terrible) manual string hacks TODO fix this bs
//string blogXml = CreateBlogXml(blogRssFeed).Replace("_x003A_", ":");
string blogXml = CreateBlogXml(blogRssFeed);
blogRssFeedModel.content = new HtmlString(blogXml);
return blogRssFeedModel;
}
/// <summary>
/// Create a rssChannelItem for the blog's rss feed.
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
public static rssChannelItem CreateRssChannelItem(IPublishedContent x) {
rssChannelItem element = new rssChannelItem();
element.description = x.GetPropertyValue<string>("excerpt");
element.link = x.Url;
element.title = x.Name;
element.pubDate = x.GetPropertyValue<DateTime>("sortDate").ToString("r");
element.guid = new rssChannelItemGuid() { isPermaLink = false, Value = x.Url };
element.mediaThumbnail = new rssChanelItemMediaThumbnail() { height = "", width = "", url = "" }; //to do populate data
return element;
}
public static string CreateBlogXml(rss node) {
System.Xml.Serialization.XmlSerializer xSerial = new System.Xml.Serialization.XmlSerializer(node.GetType());
var xns = new XmlSerializerNamespaces();
xns.Add("", "");
MemoryStream ms = new MemoryStream();
XmlTextWriter xmlTextWriter = new XmlTextWriter(ms, Encoding.UTF8);
xmlTextWriter.Formatting = Formatting.Indented;
xSerial.Serialize(xmlTextWriter, node, xns);
ms = (MemoryStream)xmlTextWriter.BaseStream;
return Encoding.UTF8.GetString(ms.ToArray());
}
Upvotes: 2
Views: 1248
Reputation: 1062512
Here:
[XmlElement(ElementName = "media:thumbnail")]
This is erroneous; the element name is thumbnail
; the namespace is http://search.yahoo.com/mrss
. media
is just a namespace alias. So the first thing we should do is fix that:
[XmlElement(ElementName = "thumbnail", Namespace = "http://search.yahoo.com/mrss")]
You are already adding the media
namespace to blogRssFeed.xmlns
:
blogRssFeed.xmlns.Add("media", "http://search.yahoo.com/mrss");
so the rest should already work from there.
Upvotes: 3