繁体   English   中英

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

[英]XML Deserialization with Servicestack.Text

我正在学习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; }
}

当我运行程序时,我得到一个例外,如下所示:

在此输入图像描述

因此,要更改Elementnamespace ,我做了以下解决方法:

我把DataContractAttribute放在我的Response类上,如下所示:

[DataContract(Namespace = "")]
public  class Response
{
   public RSS rss { get; set; }
}

我通过在反序列化之前添加以下两行来更改Element名称,如下所示

  //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>");

但是,它在foreach循环上给出了另一个例外,因为反序列化的rss对象为null 那么,我应该如何使用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的其他2个问题:

  • 它不会使用属性(在您的情况下, version
  • 它要求诸如item集合具有包装名称和元素名称(类似于项目和项目)

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

一些东西:

  1. 由于您使用的是[DataContract]属性。 必须将DTO属性包含在[DataMember]属性中,否则将在序列化/反序列化过程中跳过它们。 使用XML反序列化中指定的assembly属性仅适用于xml中的命名空间

  2. 您的xml操作需要更改以将rs包装在响应中或替换它。

    xml = xml.Replace("<rss version=\\"2.0\\">", "<Response><rss version=\\"2.0\\">");

  3. 我建议您自己构建一个测试Response对象,使用ServiceStack的.ToXml()方法将其serilialize为XML,以查看它期望的格式。 您将看到服务堆栈将通道项目处理为项目的子列表,而不是RSS格式化通道项目的方式。 您必须将所有项目包装到名为<ItemClass>的节点中

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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