class Program { static void Main(string[] args) { string str = "http://static.cricinfo.com/RSS/livescores.xml"; WebClient w = new WebClient(); string xml = w.DownloadString(str); Response RSS = xml.FromXml<Response>(); foreach (var item in RSS.RSS.Channel.item) { Console.WriteLine(item.title); } Console.Read(); } }
您可以通过str [在程序中给出]中的XML文件.我已经为反序列化准备了DTO.它们如下:
public class Response { public RSS RSS { get; set; } } public class RSS { public string Version { get; set; } public ChannelClass Channel { get; set; } } public class ChannelClass { public string title { get; set; } public string ttl { get; set; } public string description { get; set; } public string link { get; set; } public string copyright { get; set; } public string language { get; set; } public string pubDate { get; set; } public List<ItemClass> item { get; set; } } public class ItemClass { public string title { get; set; } public string link { get; set; } public string description { get; set; } public string guid { get; set; } }
当我运行程序时,我会收到如下所示的异常:
所以,要更改元素和命名空间,我做了以下解决方法:
我将DataContractAttribute放在我的Response类上,如下所示:
[DataContract(Namespace = "")] public class Response { public RSS RSS { get; set; } }
//To change RSS Element to Response as in Exception xml = xml.Replace("<RSS version=\"2.0\">","<Response>"); //For closing tag xml = xml.Replace("</RSS>","</Response>");
但是,由于反序列化的RSS对象为空,所以在foreach循环中再次出现异常.那么,如何使用Servicestack.Text以正确的方式反序列化它呢?
注意 :
我很了解如何反序列化与其他图书馆,我想只使用ServiceStack.
解决方法
ServiceStack.Text不实现自定义Xml序列化程序 – 它使用DataContractSerializer在引擎盖下. FromXml只是句法糖.
使用DataContractSerializer解析Xml
正如你所注意到的,DataContractSerializer对命名空间很挑剔.一种方法是在类上明确指定命名空间,但是如果这样做,则需要指定[DataMember],因为它假设如果任何内容是明确的,那么一切都是.您可以使用程序集级属性(例如AssemblyInfo.cs)解决此问题,以声明默认命名空间:
[assembly: ContractNamespace("",ClrNamespace = "My.Namespace.Here")]
这解决了命名空间问题.
但是,您无法使用DataContractSerializer解决其他两个问题:
>它不会使用属性(在你的情况下,版本)
>它要求诸如项目之类的集合具有包装名称和元素名称(类似于项目和项目)
您不能解决这些限制,因为DataContractSerializer不是通用的XML解析器.它旨在轻松地生成和使用API,而不是将任意的XML映射到.NET数据结构上.你永远不会得到它解析RSS;所以ServiceStack.Text(它刚刚包装它)也不能解析它.
而是使用XmlSerializer.
使用XmlSerializer
这是相当严格的您可以使用以下方式解析输入:
var serializer = new XmlSerializer(typeof(RSS)); RSS RSS = (RSS)serializer.Deserialize(myXmlReaderHere);
诀窍是注释各种字段,使它们与您的xml方言相匹配.例如,在你的情况下,将是:
[XmlRoot("RSS")] public class RSS { [XmlAttribute] public string version { get; set; } public ChannelClass channel { get; set; } } public class ChannelClass { public string title { get; set; } public string ttl { get; set; } public string description { get; set; } public string link { get; set; } public string copyright { get; set; } public string language { get; set; } public string pubDate { get; set; } [XmlElement] public List<ItemClass> item { get; set; } } public class ItemClass { public string title { get; set; } public string link { get; set; } public string description { get; set; } public string guid { get; set; } }
所以一些明智的属性就足够让它根据需要解析XML.
总而言之:您不能使用ServiceStack,因为它使用DataContractSerializer.ServiceStack / DataContractSerializer设计用于控制模式的场景.改用XmlSerializer.