使用SyndicationFeed读取RSS中<image>元素遇序列化异常求助
尝试用SyndicationFeed读取RSS feed中的<image>元素,该元素结构如下:
<image> <url>https://images.igdb.com/igdb/image/upload/t_cover_big/co25po.jpg</url> </image>
该元素出现在ElementExtensions中,无自定义命名空间。使用自定义扩展方法读取时,传入extensionName="image"会抛出SerializationException,错误信息:
'反序列化System.String类型对象时出错。预期命名空间''的结束元素'image',却找到命名空间''的元素'url'。'
传入extensionName="url"也无法找到对应元素。调用代码如下:
var reader = XmlReader.Create(_backloggdSettings.BackloggdProfileUrl); var feed = SyndicationFeed.Load(reader); var feedItems = limit > 0 ? feed.Items.Take(limit) : feed.Items; var items = feedItems.Select(i => { var imageUrl = i.ReadElementExtension("image",""); var userRating = i.ReadElementExtension("user_rating", BackloggdExtensionNamespace); var link = i.Links.FirstOrDefault()?.Uri.AbsoluteUri; return new BackloggdItem { Title = i.Title.Text, Summary = i.Summary.Text, Url = link, Rating = userRating != null ? Convert.ToDecimal(userRating) : null, ImageUrl = imageUrl, }; }); return items;
自定义扩展方法:
public static string? ReadElementExtension(this SyndicationItem item, string extensionName, string extensionNamespace) { var elementExtensions = item.ElementExtensions .ReadElementExtensions<string>(extensionName, null); //注:此处传入extensionName为"image" return elementExtensions.FirstOrDefault(); }
核心问题是<image>不是简单文本元素,而是包含子元素<url>的复合节点,直接用ReadElementExtensions<string>反序列化为字符串会失败——它期望<image>是纯文本节点,而非嵌套结构。
方法1:手动解析XML节点
修改扩展方法,直接获取<image>对应的XML节点,再提取子元素<url>的文本:
public static string? GetImageUrl(this SyndicationItem item) { var imageExtension = item.ElementExtensions.FirstOrDefault(ext => ext.OuterName == "image" && string.IsNullOrEmpty(ext.OuterNamespace)); if (imageExtension == null) return null; using (var reader = imageExtension.GetReader()) { var imageElement = XElement.Load(reader); return imageElement.Element("url")?.Value; } }
调用时替换原代码中的i.ReadElementExtension("image","")为i.GetImageUrl()即可。
方法2:定义数据类反序列化
创建匹配<image>结构的类,通过强类型反序列化获取链接:
public class RssImage { public string? Url { get; set; } } public static string? ReadImageUrl(this SyndicationItem item) { var imageElements = item.ElementExtensions .ReadElementExtensions<RssImage>("image", ""); return imageElements.FirstOrDefault()?.Url; }
调用时使用i.ReadImageUrl()获取图片链接即可。
额外修正
原扩展方法中ReadElementExtensions<string>(extensionName, null)的第二个参数硬编码为null,应改为传入参数extensionNamespace,避免后续读取其他扩展元素时出现命名空间匹配问题。
内容的提问来源于stack exchange,提问作者muttley91

