加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 使用Servicestack.Text进行XML反序列化

发布时间:2020-12-15 03:58:50 所属栏目:百科 来源:网络整理
导读:我正在学习 Servicestack.Text图书馆,因为它有一些最好的功能.我正在尝试将XML反序列入我的DTO之一,如下所示: C#代码:[相关代码与控制台应用程序在这里] class Program { static void Main(string[] args) { string str = "http://static.cricinfo.com/rss
我正在学习 Servicestack.Text图书馆,因为它有一些最好的功能.我正在尝试将XML反序列入我的DTO之一,如下所示:

C#代码:[相关代码与控制台应用程序在这里]

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.

解决方法

TLDR:使用XmlSerializer从不能控制的xml方言中反序列化; ServiceStack是专为代码优先开发而设计的,不能适应通用的xml解析.

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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读