简体   繁体   中英

C# XML Serialization Element namespace

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM