【问题标题】:XML Deserializing lists with objects only getting one level对象仅获得一级的 XML 反序列化列表
【发布时间】:2015-06-09 15:59:59
【问题描述】:

这与我在这里看到的许多问题相似,但它们都没有帮助或完全适合我的情况。我正在尝试将 SQL Server 中的 XML 输出反序列化为 C# 对象。

我拥有的类由一些属性和其他对象列表组成。问题是当它反序列化时,它只抓取每个列表的第一项。

这是我的代码:

XML:

<Product>
  <Id>2</Id>
  <Name>Foo</Name>
  <Versions>
    <Version>
      <Id>2</Id>
      <Product>Foo</Product>
      <VersionNumber>2.0</VersionNumber>
      <Resources>
        <Resource>
          <Id>5</Id>
          <Name>FunTimes</Name>
          <Uri>/fun</Uri>
          <Properties>
            <Property>
              <Id>25</Id>
              <Name>Time</Name>
              <PropertyTypeId>5</PropertyTypeId>
              <EnumerationId>7</EnumerationId>
              <Enumeration>
                <Id>7</Id>
                <Name>Time</Name>
                <Members>
                  <Member>
                    <Name>Hours</Name>
                  </Member>
                  <Member>
                    <Name>Seconds</Name>
                  </Member>
                </Members>
              </Enumeration>
            </Property>
            <Property>
              <Id>58</Id>
              <Name>Place</Name>
              <PropertyTypeId>4</PropertyTypeId>
            </Property>
          </Properties>
        </Resource>
        <Resource>
          <Id>4</Id>
          <Name>BadTimes</Name>
          <Uri>/bad</Uri>
          <Properties>
            <Property>
              <Id>25</Id>
              <Name>Cause</Name>
              <PropertyTypeId>5</PropertyTypeId>
              <EnumerationId>7</EnumerationId>
              <Enumeration>
                <Id>7</Id>
                <Name>Cause</Name>
                <Members>
                  <Member>
                    <Name>Local</Name>
                  </Member>
                  <Member>
                    <Name>International</Name>
                  </Member>
                </Members>
              </Enumeration>
            </Property>
          </Properties>
        </Resource>
      </Resources>
    </Version>
  </Versions>
</Product>

我用来反序列化的代码:

XmlSerializer deserializer = new XmlSerializer(typeof(Product));
TextReader stringReader = new StringReader(content.ToString());
object obj = deserializer.Deserialize(stringReader);
Product XmlData = (Product) obj;
stringReader.Close();

XML 存储在名为“content”的 StringBuilder 中。

这里是类:

[Serializable]
public class Product
{
    // Fields...

    // Properties    
    [XmlElement]
    public int Id { get; set; }

    [XmlElement]
    public string Name { get; set; }

    [XmlElement]
    public string Comments { get; set; }

    [XmlArray("Versions")]
    [XmlArrayItem("Version")]
    public List<Version> Versions { get; set; }

    // Constructors and methods...
}

[Serializable]
public class Version
{
    // Fields...        

    // Properties
    [XmlElement]
    public int Id { get; set; }

    [XmlElement]
    public string Product { get; set; }

    [XmlElement]
    public string VersionNumber { get; set; }

    [XmlElement]
    public string Comments { get; set; }

    [XmlArray("Resources")]
    [XmlArrayItem("Resource")]
    public List<Resource> Resources { get; set; }

    // Constructors and methods...
}

[Serializable]
public class Resource
{
    // Fields...        

    // Properties
    [XmlElement]
    public int Id { get; set; }

    [XmlElement]
    public string Name { get; set; }

    [XmlElement]
    public string Uri { get; set; }

    [XmlElement]
    public string Comments { get; set; }

    [XmlArray("Properties")]
    [XmlArrayItem("Property")]
    public List<Property> Properties { get; set; }

    // Constructors and methods...
}

[Serializable]
public class Property
{
    // Fields...

    // Properties
    [XmlElement]
    public int Id { get; set; }

    [XmlElement]
    public string Name { get; set; }

    [XmlElement]
    public PropertyType PropertyTypeId { get; set; }

    [XmlElement]
    public int? MaximumStringLength { get; set; }

    [XmlElement]
    public double? MinimumValue { get; set; }

    [XmlElement]
    public double? MaximumValue { get; set; }

    [XmlElement]
    public int? EnumerationId { get; set; }

    [XmlElement]
    public PropertyEnumeration Enumeration { get; set; }

    [XmlElement]
    public int? ResourceId { get; set; }

    [XmlElement]
    public string Comments { get; set; }

    [XmlArray("Properties")]
    [XmlArrayItem("Property")]
    public List<Property> CompositeProperties { get; set; }

    // Constructors and methods...
}

如果我将它重新序列化为 XML,这就是它给我的结果。 (我知道这不是重新序列化的错。)

<?xml version="1.0" encoding="utf-16"?>
<Product xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Id>2</Id>
  <Name>Foo</Name>
  <Versions>
    <Version>
      <Id>2</Id>
      <Product>Foo</Product>
      <VersionNumber>2.0</VersionNumber>
      <Resources>
        <Resource>
          <Id>5</Id>
          <Name>FunTimes</Name>
          <Uri>/fun</Uri>
          <Properties>
            <Property>
              <Id>25</Id>
              <Name>Time</Name>
              <PropertyTypeId>5</PropertyTypeId>
              <MaximumStringLength xsi:nil="true" />
              <MinimumValue xsi:nil="true" />
              <MaximumValue xsi:nil="true" />
              <EnumerationId>7</EnumerationId>
              <Enumeration>
                <Id>7</Id>
                <Members>
                  <Member>Hours</Member>
                </Members>
              </Enumeration>
              <ResourceId xsi:nil="true" />
            </Property>
          </Properties>
        </Resource>
      </Resources>
    </Version>
  </Versions>
</Product>

还有一个 Enumeration 类和一些其他帮助类,但它们并不重要。基本上我需要它来给我 XML 中的其余项目。我试过让列表属性使用 XmlElement 标记,但这会产生相同的结果。如何让它读取 XML 中的所有项目?

编辑:奥列格在评论中提到它对他有用。有谁知道我的系统是否会特别混乱?

编辑:找到了解决方案。很遗憾,我什至没有为您提供足够的信息来解决它。在 XML 中,它说

<Members>
  <Member>
    <Name>Local</Name>
  </Member>
  <Member>
    <Name>International</Name>
  </Member>
</Members>

在枚举下。在我的 Enumeration 类中,我有一个属性,它是一个名为 Members 的字符串列表。它期待一个内部具有 Name 属性的成员列表,所以它吓坏了。通过将其更改为

<Members>
  <Member>Local</Member>
  <Member>International</Member>
</Members>

它解决了这个问题。

【问题讨论】:

  • 我试图通过使用此类创建项目来重现您的问题,但在我的情况下,所有序列化都很好,XmlData.Versions 集合中有两个项目。
  • @Oleg 这可能与我的一般设置有关吗?我不知道是什么导致它无法在我的系统上运行。
  • 附带说明,请看这里:felinesoft.com/blog/index.php/2014/07/…
  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。

标签: c# xml serialization


【解决方案1】:

试试这个。我使用了一个文件,所以我替换了文本阅读器。您不需要两个级别的项目,例如属性和属性。如果更改 XML,则可以消除一级

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

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XmlSerializer xs = new XmlSerializer(typeof(Product));
            XmlTextReader reader = new XmlTextReader(FILENAME);
            Product XML = (Product)xs.Deserialize(reader);
        }
    }
    [XmlRoot("Product")]
    public class Product
    {
        // Fields...

        // Properties    
        [XmlElement("Id")]
        public int Id { get; set; }

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

        private string Comments { get; set; }

        [XmlElement("Versions")]
        public Versions Versions { get; set; }

        // Constructors and methods...
    }
    [XmlRoot("Versions")]
    public class Versions
    {
        [XmlElement("Version")]
        public List<Version> Version { get; set; }
    }

    [XmlRoot("Version")]
    public class Version
    {
        // Fields...        

        // Properties
        [XmlElement("Id")]
        public int Id { get; set; }

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

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

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

        [XmlElement("Resources")]
        public Resources Resources { get; set; }

        // Constructors and methods...
    }

    [XmlRoot("Resourses")]
    public class Resources
    {
        [XmlElement("Resource")]
        public List<Resource> Resource { get; set; }
    }
    [XmlRoot("Resourse")]
    public class Resource
    {
        // Fields...        

        // Properties
        [XmlElement("Id")]
        public int Id { get; set; }

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

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

        private string Comments { get; set; }

        [XmlElement("Properties")]
        public Properties Properties { get; set; }
    }
        // Constructors and methods.
    [XmlRoot("Properties")]
    public class Properties
    {
        [XmlElement("Property")]
        public List<Property> properties { get; set; }
    }
    [XmlRoot("Property")]
    public class Property
    {
        // Fields...

        // Properties
        [XmlElement("Id")]
        public int Id { get; set; }

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

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

        private int? MaximumStringLength { get; set; }

        private double? MinimumValue { get; set; }

        private double? MaximumValue { get; set; }

        [XmlElement("EnumerationId")]
        public int? EnumerationId { get; set; }

        private int? ResourceId { get; set; }

        private string Comments { get; set; }

        [XmlElement("Enumeration")]
        public Enumeration Enumeration { get; set; }

        // Constructors and methods...
    }
    [XmlRoot("Enumeration")]
    public class Enumeration
    {
        [XmlElement("Id")]
        public int Id { get; set; }

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

        [XmlElement("Members")]
        public Members Members { get; set; }
    }
    [XmlRoot("Members")]
    public class Members
    {
        [XmlElement("Member")]
        public List<Member> Member { get; set; }
    }
    [XmlRoot("Member")]
    public class Member
    {
        [XmlElement("Name")]
        public string Name { get; set; }
    }
}
​

【讨论】:

  • 不幸的是,这并没有做任何事情。我得到了同样的结果。
  • 我对课程进行了全面测试。我所做的唯一区别是添加第一行 "" 。尝试这样做: TextReader stringReader = new StringReader("" + content.ToString());
  • 这真的很奇怪,因为即使添加 xml 版本行对我也没有任何作用。
  • 尝试完全按原样运行我的代码,看看是否得到了好/坏的结果。
猜你喜欢
  • 2020-10-31
  • 1970-01-01
  • 2013-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多