簡體   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