【问题标题】:C# XML Serialization un-nested arrays/listC# XML 序列化非嵌套数组/列表
【发布时间】:2016-04-02 23:25:46
【问题描述】:

我正在编写一个 C# WinForm 应用程序,它应该读取一个预先存在的 XML 文件。 我需要解析XML 文件并建立一个数据结构来反映XML 文件内容。 我在XML 序列化方面有一些经验,因此我坚持使用.NET XML.Serialization 功能。 我陷入了一个奇怪的XML 结构中,我无法在类中匹配(通过属性、元素等):

<sheet number="1" name="/" tstamps="/">
  <title_block>
    <title>ECC Push-Pull</title>
    <company/>
    <rev>0.1</rev>
    <date>Sat 21 Mar 2015</date>
    <source>ecc83-pp.sch</source>
    <comment number="1" value=""/>
    <comment number="2" value=""/>
    <comment number="3" value=""/>
    <comment number="4" value=""/>
  </title_block>
</sheet>

其中“奇怪”的部分是 cmets 列表。由于使用 XmlArray 指令对元素列表/数组进行序列化,我习惯于查找此类“重复”项目。无论如何,使用这种方法会引入一个环绕标签来包含项目列表。在这种情况下,我如何“反映”这种结构? 这是我应该使用的代码(没有“缺失”的 cmets):

[XmlRoot("sheet")]
public class Sheet
{
    [XmlAttribute("number")]
    public int Number { get; }

    [XmlAttribute("name")]
    public string Name { get; set; }

    [XmlAttribute("tstamps")]
    public UInt32 TimeStamps { get; set; }

    [XmlElement]
    public SheetTitle Title { get; set; }

    public Sheet()
    {
        Title = new SheetTitle();
    }
}


[XmlRoot("title_block")]
public class SheetTitle
{
    [XmlElement("title")]
    public string Title { get; set; }

    [XmlElement("company")]
    public string Company { get; set; }

    [XmlElement("rev")]
    public string Revision { get; set; }

    [XmlElement("date")]
    public DateTime Date { get; set; }

    [XmlElement("source")]
    public string Source { get; set; }

    public SheetTitle()
    {
        Date = DateTime.Now;
    }
}

[XmlRoot("comment")]
public class Comment
{
    [XmlAttribute("number")]
    public int Number { get; set; }

    [XmlAttribute("value")]
    public string Value { get; set; }
}

我还有另一个问题。反映这种结构的最佳类层次结构是: a) 以与 xml 元素相同的方式嵌套类 b) 将所有类保持在同一级别(没有层次结构)? 有副作用需要考虑吗?

【问题讨论】:

标签: c# xml xml-serialization


【解决方案1】:

试试这个...

用途

using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

[XmlRoot(ElementName = "comment")]
public class Comment
{
    [XmlAttribute(AttributeName = "number")]
    public string Number { get; set; }
    [XmlAttribute(AttributeName = "value")]
    public string Value { get; set; }
}

[XmlRoot(ElementName = "title_block")]
public class Title_block
{
    [XmlElement(ElementName = "title")]
    public string Title { get; set; }
    [XmlElement(ElementName = "company")]
    public string Company { get; set; }
    [XmlElement(ElementName = "rev")]
    public string Rev { get; set; }
    [XmlElement(ElementName = "date")]
    public string Date { get; set; }
    [XmlElement(ElementName = "source")]
    public string Source { get; set; }
    [XmlElement(ElementName = "comment")]
    public List<Comment> Comment { get; set; }
}

[XmlRoot(ElementName = "sheet")]
public class Sheet
{
    [XmlElement(ElementName = "title_block")]
    public Title_block Title_block { get; set; }
    [XmlAttribute(AttributeName = "number")]
    public string Number { get; set; }
    [XmlAttribute(AttributeName = "name")]
    public string Name { get; set; }
    [XmlAttribute(AttributeName = "tstamps")]
    public string Tstamps { get; set; }
}

代码

try
{
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load("xml.xml");

    string XML = xmlDoc.InnerXml.ToString();
    byte[] BUFXML = ASCIIEncoding.UTF8.GetBytes(XML);
    MemoryStream ms1 = new MemoryStream(BUFXML);

    XmlSerializer DeserializerPlaces = new XmlSerializer(typeof(Sheet));
    using (XmlReader reader = new XmlTextReader(ms1))
    {
        Sheet dezerializedXML = (Sheet)DeserializerPlaces.Deserialize(reader);

    }// Put a break-point here, then mouse-over dezerializedXML and you should have you values
}
catch (System.Exception)
{
    throw;
}

此代码从一个文件(应用程序 *.exe 文件夹中称为 xml.xml)中读取您的 xml,然后将其反序列化为一个名为 dezerializedXML 的对象...。

【讨论】:

    【解决方案2】:

    您可以按如下方式定义您的 C# 对象。

    [XmlRoot(ElementName="comment")]
    public class Comment {
        [XmlAttribute(AttributeName="number")]
        public string Number { get; set; }
        [XmlAttribute(AttributeName="value")]
        public string Value { get; set; }
    }
    
    [XmlRoot(ElementName="title_block")]
    public class Title_block {
        [XmlElement(ElementName="title")]
        public string Title { get; set; }
        [XmlElement(ElementName="company")]
        public string Company { get; set; }
        [XmlElement(ElementName="rev")]
        public string Rev { get; set; }
        [XmlElement(ElementName="date")]
        public string Date { get; set; }
        [XmlElement(ElementName="source")]
        public string Source { get; set; }
        [XmlElement(ElementName="comment")]
        public List<Comment> Comment { get; set; }
    }
    
    [XmlRoot(ElementName="sheet")]
    public class Sheet {
        [XmlElement(ElementName="title_block")]
        public Title_block Title_block { get; set; }
        [XmlAttribute(AttributeName="number")]
        public string Number { get; set; }
        [XmlAttribute(AttributeName="name")]
        public string Name { get; set; }
        [XmlAttribute(AttributeName="tstamps")]
        public string Tstamps { get; set; }
    }
    

    现在我们可以使用这些实体来Deserialize给定Xml。

    XmlSerializer serializer = new XmlSerializer(typeof(Sheet));
    
    StreamReader reader = new StreamReader(filepath);
    var sheet = (Sheet)serializer.Deserialize(reader);
    reader.Close();
    

    检查这个Demo code

    【讨论】:

      猜你喜欢
      • 2016-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多