2

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

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.